JavaScript 符号不会阻止对象中的名称冲突

Posted

技术标签:

【中文标题】JavaScript 符号不会阻止对象中的名称冲突【英文标题】:JavaScript Symbols are not stopping name ***es in Objects 【发布时间】:2018-11-21 04:36:48 【问题描述】:

我已经开始研究 javascript 中的符号,并开始在我的对象中使用它们来帮助解决名称冲突,但是在使用它们时我仍然可以覆盖属性吗?我很难理解符号在 JavaScript 中的意义。他们被谈论了很多,人们说他们很聪明,因为他们不会在对象中引起命名冲突,但我看不出是怎么回事?

    // Create your object
let obj = ;

// Create your Symbol
let address = Symbol("the address symbol");

// Assign your Symbol as a key to a value
obj[address] = "123 Bond street";

// Return '123 Bond street'
console.log(obj[address])


// Another dev comes along

// Assigns an address property to your object
obj[address] = "456 Regent street";

// Your address property has been overwritten?
console.log(obj[address])

从我的代码中可以看出,我仍然可以覆盖对象上的属性吗?那么 Symbol 有什么帮助呢?

我用错了吗?

【问题讨论】:

当然,您正在覆盖该属性。您创建的符号存储在address 中,然后您设置了该键两次。您的代码只是生成一个动态唯一符号,然后将其静态存储。 它会停止obj.address = "456 Regent street"; @dandavis 当然会,因为address 从一开始就不是键名。 @ScottMarcus: 对,所以如果你控制对本地的访问,你就控制对道具的访问...... 您需要创建第二个符号:const address2 = Symbol("the address symbol");。如果您的代码确实避免了名称冲突,您将如何更新使用 Symbol 键存储的属性? 【参考方案1】:

您的印象似乎是每次访问address 时都会分配一个新的不同符号值,这是不正确的。

您所做的只是使用 Symbol 生成一个唯一值,然后将该值存储在 address 变量中。这意味着当您稍后再次使用它时,您使用的是之前生成的相同符号。即使您不使用 Symbol 也会出现这种情况:

let obj = ;   // Create your object
    
let address = "some key name";
obj[address] = "123 Bond street";  
console.log(obj[address]);  // Return '123 Bond street'
    
// Another dev comes along
obj[address] = "456 Regent street";   // Assigns an address property to your object
console.log(obj[address]);  // Your address property has been overwritten

简而言之,如果您存储一个符号,那么您所做的只是存储了一个保证唯一的值。但是,这并不能阻止您一遍又一遍地使用它。

Symbol 更合适的用途是防止其他开发人员在现有对象上创建一个 new 键,该键与从其他符号:

let obj = ;   // Create your object
    
let address = Symbol("some key name");
obj[address] = "123 Bond street";  
console.log(obj[address]);  // Return '123 Bond street'
    
// Another dev comes along
let newProp = Symbol("some key name");
obj[newProp] = "456 Regent street";   // Guaranteed unique new key is created

// There is no way the two properties would ever overwrite each other because each
// was created from a different Symbol
console.log(obj[address]);  
console.log(obj[newProp]);

【讨论】:

嗨@ScottMarcus,是否也可以使用字符串而不是符号来显示您的最后一个示例,并解释如何覆盖字符串键,因为我无法引用理解,(我已经使用字符串写出了代码,但结果是一样的,我无法理解可能覆盖属性的情况,我的意思是我知道是否有人试图创建一个现有的字符串变量属性将覆盖现有的,但如果他们创建另一个符号并将其分配给原始变量,情况也是如此)。谢谢。 @Zippy 我不确定我是否遵循。上面的示例在不使用符号时几乎相同,只需删除new Symbol("some key name") 并将其替换为"some key name"。那么问题就在于有人可以使用已经使用过的相同密钥名称,从而覆盖密钥中的内容。 @ScorrMarcus,感谢您的回复。我的意思是,我看到的每个示例都显示其他人出现并尝试创建对象的属性,例如该属性已经存在的“年龄”。如果我们然后访问'age',它将返回新值(这是预期的),但是它们随后使用符号显示类似的示例,但是当尝试创建新属性(存在一个)时,它们总是显示它们使用不同的变量名,这显然不会覆盖原来的。抱歉,如果仍然不清楚。我只是很难解决所有问题!谢谢。 这正是我最后一个示例所显示的。第一个属性名称由符号生成并存储在address 变量中,第二个属性名称是从不同符号生成的不同值并存储在newProp 变量中。

以上是关于JavaScript 符号不会阻止对象中的名称冲突的主要内容,如果未能解决你的问题,请参考以下文章

jQuery名称冲突

如何解决 Cocoa touch 框架中的符号名称冲突

JavaScript - Symbol类型

JavaScript - Symbol类型

C++中的函数名称粉碎机制和它的逆向应用(符号冲突函数重名变量重名)

jquery里面的美元符号代表啥?