@Dale-Lin
2021-07-11T18:03:36.000000Z
字数 2687
阅读 823
深入理解ES6
ES6 引入新的类型 Symbol。
symbol 类型属于一种基本类型。
const bar = Symbol('bar') // local symbol
const foo = Symbol.for('foo') // global symbol
typeof bar // 'symbol'
typeof foo // 'symbol
通过全局的 symbol 函数创建一个 Symbol:
let firstName = Symbol();
let person = {};
person[firstName] = "Nicholas";
console.log(person[firstName]); //"Nicholas"
第一行创建了一个名为 firstName 的 Symbol。当用其作为属性名的时候,必须通过这个 Symbol 来进行访问。
Symbol 函数接受一个描述的可选参数:
let firstName = Symbol("first name");
console.log(firstName); //"Symbol(first name)"
所有使用可计算属性名的地方都可以使用 Symbol:
let firstName = Symbol("first name");
let person = {
[firstName]: "Nicholas"
};
Object.defineProperty(person, firstName, {
writable: false;
});
let lastName = Symbol("last name");
Object.defineProperties(person, {
[lastName]: {
value: "Zakas",
writable: false
}
});
使用 Symbol.for()
方法创建一个可共享的 Symbol:
let uid = Symbol.for("uid");
let obj = {};
obj[uid] = "12345";
console.log(obj[uid]); //"12345"
console.log(uid); //"Symbol(uid)"
Symbol.for()
方法先在全局 Symbol 注册表中搜索键为 "uid" 的 Symbol 是否存在,若存在,直接返回已存在的 Symbol;否则,创建一个新的 Symbol 并注册。
后续再传入同样的键调用 Symbol.for()
会返回相同的 Symbol:
let uid = Symbol.for("uid");
let obj = {};
obj[uid] = "12345";
console.log(obj[uid]); //"12345"
console.log(uid); //"Symbol(uid)"
let uid2 = Symbol.for("uid");
console.log(uid === uid2); //true
Object.keys()
和 Object.getOwnPropertyNames()
可以检索对象中所有的属性名:前一个返回所有可枚举属性名;后一个无视枚举性全部返回。但都不支持 Symbol 属性。
ES6 添加了 Object.getOwnPropertySymbols()
方法来检索对象中的 Symbol 属性,返回包含所有 Symbol 自有属性的数组:
let uid = Symbol.for("uid");
let object = {
[uid]: "12345"
};
let symbols = Object.getOwnPropertySymbols(object);
console.log(symbols[length]); //1
console.log(symbols[0]); //"Symbol(uid)"
Symbol.hasInstance(instance)
一个在执行 instanceof 时调用的内部方法,用于检测对象的继承信息。
每个函数中都有一个 Symbol.hasInstance(instance) 方法,用于确定对象是否为函数的实例,但默认为不可写、不可设置且不可枚举。
obj instanceof Array;
这行代码等价于:
Array[Symbol.hasInstance](obj)
ES6中可以重新定义 Symbol.hasInstance 来改变 instanceof 调用时的行为:
function MyObject() {
//empty
}
Object.defineProperty(MyObject, Symbol.hasInstance, {
value: function(instance) {
return false;
}
});
let obj = new MyObject();
console.log(obj instanceof MyObject); //false
也可以用来检查:
function SpecialNumber() {
//empty
}
Object.defineProperty(SpecialNumber, Symbol.hasInstance, {
value: function(instance) {
return (instance instanceof Number) && (instance >= 1 && instance <= 100);
}
});
let two = new Number(2),
zero = new Number(0);
console.log(two instanceof SpecialNumber, zero instanceof SpecialNumber); //true, false
Symbol.isConcatSpreadable
Array.prototype.concat() 方法也可以接受多个包含数组的参数,并将数组分解成独立元素后拼接。
Symbol.isConcatSpreadable 属性是一个布尔值,如果该属性值为 true,则表示对象有 length 属性和数字键,故他的数值型属性值应该被独立添加到 concat() 调用的结果中:
let collection = {
0: "Hello",
1: "world",
length: 2,
[Symbol.isConcatSpreadable]: true
};
let message = ["Hi"].concat(collection);
console.log(message); //["Hi", "Hello", "world"];
也可以在派生数组子类中将 Symbol.isConcatSpreadable 设置为 false,从而防止元素在调用 concat() 时被分解。