Symbol
es6引入了一个新的数据类型Symbol,用于表示独一无二的值,他是JavaScript第七种数据类型。
Symbol值通过Symbol函数生成,但是不需要new,用于解决属性名容易被人复写的问题。
目前对象的属性名都是string类型,也就是字符串,现在新增了symbol类型,只要属性名是symbol类型,就是独一无二的,可以保证不会与其他属性名产生冲突。
let s = Symbol();
typeof s //"symbol"
基本使用
Symbol函数接收一个字符串参数,表示对Symbol实例的描述,主要是为了再控制台显示,而且即便两个Symbol使用同一个字符串描述,他们也是不相等的。
let s = Symbol("foo");
let a = Symbol("foo");
s === a //false
s.toString(); // "foo"
a.toString(); // "foo"
symbol可以转换为布尔值或者字符串,但是无法被转换为数值。
作为属性名的Symbol
由于每一个symbol值都是不相等的,这意味着symbol可以作为标识符用于对象的属性名,保证不会出现重名,特别是在一些一个对象有多个模块组成,有继承的情况下,能防止某一个键不会被改写或覆盖。
var my = Symbol();
//第一种写法
var a = {};
a[my] = "第一种";
//第二种
var b = {
[my]: "第二种"
}
//第三种
var c = {};
Object.difineProperty(c,my,{value:"第三种"});
//以上写法都可以
注意一点就是symbol不能使用点运算符,因为他不是string,如果使用点运算符来作为对象的属性名,会被识别为字符串
var my = Symbol();
var a = {};
a.my = "xxx";
//a.my 等于 a["my"]
所以,在作为属性名时,是需要方括号包裹的
var my = Symbol();
var a = {};
a[my] = "xxx";
var b = {
[my]: "第二种"
}
var c = {
[my]() {
//函数
}
}
属性名的遍历
symbol作为属性名,该属性不会出现在for...in、for...of
循环中,也不会被Object.keys()、Object.getOwnPropertyNames()返回,但他不是私有属性,可以通过Object.getOwnPropertysSymbols()
方法获取指定对象的所有symbol属性名
该方法返回一个数组,成员为当前对象的所有作为属性名的symbol值
var my = Symbol();
var a = {};
a[my] = "xxx";
var symbolArr = Object.getOwnPropertysSymbols(a);
symbolArr; //[Symbol()]
es6新增了一个新的apiReflect.ownKeys()
,可以返回所有类型的键名,包括常规的string和symbol,也是一个数组。
var my = Symbol();
var a = {
d: "xxx"
};
a[my] = "xxx";
var arr = Reflect.ownKeys(a);
arr; //["d",Symbol()]
symbol无法被常规方法遍历到,我们可以利用这个特性为对象定义一些非私有但是又希望只用于内部的方法。
具体暂时还不明白用法,等学了class再看看。
Symbol.for()、Symbol.keyFor()
有时,我们希望能重新使用同一个symbol值,于是有了symbol.for,使用该方法创建的symbol,他也接收一个字符串作为参数,然后他会进行全局搜索,如果全局里面没有以这个参数作为名称的symbol值,就创建一个,有的话就返回对应的已经存在的symbol
var a = Symbol.for("foo");
var b = Symbol.for("foo");
a===b; //true
但是这个相等是有前提的,是一定是for创建的,因为Symbol()
他创建的永远是唯一的,而Symbol.for()
创建的,他其实是有查询表的,类似于在全局有一张键值对的表,每次都是查询这个表,有就拿,没有就创建。
所以:
var a = Symbol.for("foo");
var b = Symbol("foo");
a===b; //false
她两是不相等的。
而Symbol.keyFor()
就是用来判断,全局的那张查询表是否存在这个已经登记的symbol
var a = Symbol.for("foo");
Symbol.keyFor(a); //"foo"
var b = Symbol("foo");
Symbol.keyFor(b); //undefined
Symbol.keyFor()
会直接返回那个已经登记的key,没有则是undefined
注意:
由于Symbol.for
创建的是全局的,所有,可以在不同的iframe或者service worker中使用同一份symbol对象
var iframe = document.createElement("iframe");
iframe.src = String(window.location);
document.body.appendChild(iframe);
iframe.contentWindow.Symbol.for("foo") === Symbol.for("foo");
//true
contentWindow
可以获取到iframe的window对象,也就是全局对象,他的全局对象Symbol使用for创建一个symbol,按道理,他应该是iframe中的,不可能和外面的Symbol.for("foo")
相等,但是由于都在同一个页面下,所以是相等的,因为symbol的登记是全局环境的。
Symbol内置值
es6里面通过一些新的属性,对原来的一些对象属性进行了调整,配合Symbol进行了调整,具体就不多说了,目前也没想到哪里需要用到,等需要了再百度吧。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据