Yan*_*nis 344 javascript symbols ecmascript-harmony ecmascript-6
更新:最近一篇来自Mozilla的精彩文章出现了.如果你好奇,请阅读它.
您可能知道他们计划在ECMAScript 6中包含新的Symbol原语类型(更不用说其他一些疯狂的东西).我一直认为:symbol
Ruby 中的概念是不必要的; 我们可以轻松地使用纯字符串,就像我们在JavaScript中一样.现在他们决定用JS复杂化JS.
我不明白动机.有人可以向我解释我们是否真的需要JavaScript中的符号吗?
And*_*erg 217
将符号引入Javascript的最初动机是启用私有属性.
不幸的是,他们最终被严重降级.它们不再是私有的,因为您可以通过反射找到它们,例如,使用Object.getOwnPropertySymbols
或代理.
它们现在被称为唯一符号,它们唯一的用途是避免属性之间的名称冲突.例如,ECMAScript本身现在可以通过某些方法引入扩展钩子,这些方法可以放在对象上(例如,定义它们的迭代协议),而不会有与用户名冲突的风险.
这是否足够强大,为语言添加符号的动机是值得商榷的.
Sam*_*nda 89
符号不保证真正的隐私,但可用于分隔对象的公共和内部属性.让我们举一个例子,我们可以用它Symbol
来拥有私有财产.
让我们举一个例子,其中对象的属性不是私有的.
var Pet = (function() {
function Pet(type) {
this.type = type;
}
Pet.prototype.getType = function() {
return this.type;
}
return Pet;
}());
var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Modified outside
console.log(a.getType());//Output: null
Run Code Online (Sandbox Code Playgroud)
上面,Pet
类属性type
不是私有的.为了使它成为私有,我们必须创建一个闭包.下面的例子说明了我们如何type
使用闭包来私有化.
var Pet = (function() {
function Pet(type) {
this.getType = function(){
return type;
};
}
return Pet;
}());
var b = new Pet('dog');
console.log(b.getType());//dog
b.type = null;
//Stays private
console.log(b.getType());//dog
Run Code Online (Sandbox Code Playgroud)
上述方法的缺点:我们为每个Pet
创建的实例引入了一个额外的闭包,这可能会损害性能.
现在我们介绍Symbol
.这可以帮助我们将属性设为私有,而无需使用额外的不必要的闭包.代码示例如下:
var Pet = (function() {
var typeSymbol = Symbol('type');
function Pet(type) {
this[typeSymbol] = type;
}
Pet.prototype.getType = function(){
return this[typeSymbol];
}
return Pet;
}());
var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Stays private
console.log(a.getType());//Output: dog
Run Code Online (Sandbox Code Playgroud)
Mih*_*nut 37
Symbols
是一种新的,特殊的对象,可以在对象中用作唯一的属性名称.使用Symbol
而不是string
's允许不同的模块创建不相互冲突的属性.Symbols
也可以是私有的,这样任何没有直接访问权限的人都无法访问他们的属性Symbol
.
Symbols
是一个新的原语.就像number
,string
和boolean
原语,Symbol
有可用于创建它们的功能.不像其他的原语,Symbols
没有文字语法(例如,如何string
有''
) -创建它们与唯一的办法Symbol
以下列方式构造:
let symbol = Symbol();
Run Code Online (Sandbox Code Playgroud)
实际上,Symbol
将属性附加到对象只是一种稍微不同的方式 - 您可以轻松地提供众所周知的Symbols
标准方法,就像Object.prototype.hasOwnProperty
在继承的所有内容中出现的那样Object
.
以下是Symbol
原始类型的一些好处.
Symbols
内置可调试性Symbols
可以给出一个描述,它实际上只是用于调试,以便在将它们登录到控制台时使生活更容易.
Symbols
可以用作Object
键这是Symbol
真正有趣的地方.它们与物体交织在一起.Symbol
可以指定为对象的键,这意味着您可以为对象分配无限数量的唯一值,Symbol
并保证它们永远不会与string
键或其他唯一的冲突Symbols
.
Symbols
可以用作唯一值.让我们假设你有一个日志库,其中包括多个日志级别,例如logger.levels.DEBUG
,logger.levels.INFO
,logger.levels.WARN
等等.在ES5代码中,你想要制作这些string
(所以logger.levels.DEBUG === 'debug'
)或number
s(logger.levels.DEBUG === 10
).这两个都不理想,因为这些值不是唯一值,但Symbol
s是!所以logger.levels
简单地变成:
log.levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');
Run Code Online (Sandbox Code Playgroud)
阅读这篇精彩的文章.
nic*_*ael 36
这篇文章是关于的Symbol()
,提供了我可以找到/制作的实际例子以及我能找到的事实和定义.
这Symbol()
是数据类型,随ECMAScript 6(ES6)的发布而引入.
关于符号有两个奇怪的事实.
第一个数据类型,只有JavaScript中没有文字的数据类型
任何用Symbol()
它定义的变量都会获得独特的内容,但它并不是真正的私有.
任何数据都有自己的符号,对于相同的数据,符号将是相同的.以下段落中的更多信息,否则它不是TLRD; :)
你可以这样做:
var mySymbol1 = Symbol();
Run Code Online (Sandbox Code Playgroud)
或者这样:
var mySymbol2 = Symbol("some text here");
Run Code Online (Sandbox Code Playgroud)
该"some text here"
字符串不能从符号中提取,它只是用于调试目的的描述.它不会以任何方式改变符号的行为.虽然,你可以console.log
(这是公平的,因为该值是用于调试,以免错误地将该日志与其他日志条目一起):
console.log(mySymbol2);
// Symbol(some text here)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,实际上考虑了符号的值,这样两个符号可以是非唯一的.
var a1 = Symbol.for("test");
var a2 = Symbol.for("test");
console.log(a1 == a2); //true!
Run Code Online (Sandbox Code Playgroud)
我们将这些符号称为"第二类"符号.它们不Symbol(data)
以任何方式与"第一类型"符号(即用其定义的符号)相交.
接下来的两段仅涉及第一类符号.
我们首先考虑一个对象,一个标准数据类型.我们可以在那里定义一些键值对,并通过指定键来访问值.
var persons = {"peter":"pan","jon":"doe"};
console.log(persons.peter);
// pan
Run Code Online (Sandbox Code Playgroud)
如果我们有两个名叫彼得的人怎么办?
这样做:
var persons = {"peter":"first", "peter":"pan"};
Run Code Online (Sandbox Code Playgroud)
没有多大意义.
因此,似乎是两个完全不同的人具有相同名称的问题.让我们再提出新的Symbol()
.它就像现实生活中的一个人 - 任何人都是独一无二的,但他们的名字可以是平等的.让我们定义两个"人".
var a = Symbol("peter");
var b = Symbol("peter");
Run Code Online (Sandbox Code Playgroud)
现在我们有两个同名的人.我们的人确实不同吗?他们是; 你可以检查一下:
console.log(a == b);
// false
Run Code Online (Sandbox Code Playgroud)
我们如何在那里受益?
我们可以在您的对象中为不同的人创建两个条目,并且它们不会以任何方式被误解.
var firstPerson = Symbol("peter");
var secondPerson = Symbol("peter");
var persons = {[firstPerson]:"first", [secondPerson]:"pan"};
Run Code Online (Sandbox Code Playgroud)
注意:
值得注意的是,对象进行字符串化JSON.stringify
将删除所有以Symbol作为键初始化的对.
执行Object.keys
不会返回这样的Symbol()->value
对.
使用此初始化,绝对不可能将条目误认为是第一人和第二人.调用console.log
它们将正确输出其第二个名称.
console.log(persons[a]);
// first
console.log(persons[b]);
// pan
Run Code Online (Sandbox Code Playgroud)
实际上,已经存在一种定义要隐藏Object.keys
和枚举的属性的方法.这里是:
var anObject = {};
var fruit = "apple";
Object.defineProperty( anObject, fruit, {
enumerable: false,
value: "green"
});
Run Code Online (Sandbox Code Playgroud)
那Symbol()
带来了什么区别?不同之处在于您仍然可以通过Object.defineProperty
以下方式获取定义的属性:
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //green
console.log(anObject.apple); //green
Run Code Online (Sandbox Code Playgroud)
如果使用符号定义,如上一段所述:
fruit = Symbol("apple");
Run Code Online (Sandbox Code Playgroud)
只有知道变量即可以获得其价值
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //undefined
console.log(anObject.apple); //undefined
Run Code Online (Sandbox Code Playgroud)
此外,在键下定义另一个属性"apple"
将使对象删除较旧的属性(如果硬编码,则可能抛出错误).所以,不再是苹果!这真遗憾.参考前一段,符号是唯一的,并定义一个键,因为Symbol()
它将使其独特.
与其他数据类型不同,无法将其转换Symbol()
为任何其他数据类型.
可以通过调用基于原始数据类型"制作"符号Symbol(data)
.
在检查类型方面,没有任何变化.
function isSymbol ( variable ) {
return typeof someSymbol === "symbol";
}
var a_Symbol = Symbol("hey!");
var totally_Not_A_Symbol = "hey";
console.log(isSymbol(a_Symbol)); //true
console.log(isSymbol(totally_Not_A_Symbol)); //false
Run Code Online (Sandbox Code Playgroud)Cho*_*ang 18
我就是这样看的.符号通过阻止对象的键/属性通过一些流行的方法(如Object.keys()和JSON.stringify())来提供"额外的隐私级别".
var age = Symbol(); // declared in another module perhaps?
class Person {
constructor(n,a){
this.name = n;
this[age] = a;
}
introduce(){
console.log(`My name is ${this.name}. I am ${this[age]-10}.`);
}
}
var j = new Person('Jane',45);
j.introduce(); // My name is Jane. I am 35.
console.log(JSON.stringify(j)); // {"name":"Jane"}
console.log(Object.keys(j)); // ["name"]
console.log(j[age]); // 45 (well…only if you know the age in the first place…)
Run Code Online (Sandbox Code Playgroud)
尽管给定了一个对象本身,但仍然可以通过反射,代理,Object.getOwnPropertySymbols()等公开这些属性,没有通过一些直接方法访问它们的自然方法,从OOP的角度来看,这有时可能就足够了.
归档时间: |
|
查看次数: |
52044 次 |
最近记录: |