- Symbol类型持有特性
- 1-类型是symbol,可通过typeof关键字去取的
- 2-不能使用new执行,所以instanceof 结果是false
- 3-Symbol函数接受一个字符串作为参数,表示对Symbol实例的描述
- 4-如果Symbol的参数是对象,就调用该对象的toString(),转为字符串后,才生成一个Symbol值
- 5-值是唯一的,无论是传相同的参数还是不传参
- 6-不能与其他类型进行运算,会报错
- 7-显示可以转为字符串
- 8-Symbol 值可以作为标识符,用于对象的属性名,可以保证不会出现同名的属性
- 9-Symbol作为属性名,不会出现在for…in,for…of,Object.keys(),Object.getOwnPropertyNames(),JSON.stringify()返回,只有Object.getOwnPropertySymbols方法可以返回
- 10-如果我们希望使用同一个Symbol值,可以用Symbol.for(),接受一个字符串作为参数,搜索有没有该参数做为名称的Symbol值,有就返回这个值,否则就新建
- 11-Symbol.keyFor()返回一个已登记的Symbol类型值的key
- 实现
Symbol类型持有特性
1-类型是symbol,可通过typeof关键字去取的
let s = Symbol();
typeof s; // "symbol"
2-不能使用new执行,所以instanceof 结果是false
因为生成的Symbol是个原始类型的值,不是对象
let s = Symbol();
s instanceof Symbol; // false
3-Symbol函数接受一个字符串作为参数,表示对Symbol实例的描述
let s = Symbol("str");
console.log(s); // Symbol(str)
4-如果Symbol的参数是对象,就调用该对象的toString(),转为字符串后,才生成一个Symbol值
const obj = {
toString() {
return "abc";
}
}
let s = Symbol(obj);
console.log(s); // Symbol(abc)
5-值是唯一的,无论是传相同的参数还是不传参
// 没有参数
let s1 = Symbol();
let s2 = Symbol();
s1 === s2; // false
// 相同参数
let s3 = Symbol("str");
let s4 = Symbol("str");
s3 === s4; // false
6-不能与其他类型进行运算,会报错
let s = Symbol("str");
"my" + s; // Uncaught TypeError:Cannot convert a Symbol value to a string
7-显示可以转为字符串
let s = Symbol("str");
String(s); // Symbol(str)
s.toString(s); // Symbol(str)
8-Symbol 值可以作为标识符,用于对象的属性名,可以保证不会出现同名的属性
let s = Symbol();
// 第一种写法
let a = {};
a[s] = "hello";
// 第二种写法
let a = {
[s]: "hello"
};
// 第三种写法
let a = {};
Object.defineProperty(a, s, {value: "hello"});
// 以上都是同样的结果
a[s]; // "hello"
9-Symbol作为属性名,不会出现在for…in,for…of,Object.keys(),Object.getOwnPropertyNames(),JSON.stringify()返回,只有Object.getOwnPropertySymbols方法可以返回
let obj = {};
let a1 = Symbol("a");
let b1 = Symbol("b");
obj[a1] = "hello";
obj[b1] = "world";
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(a), Symbol(b)]
10-如果我们希望使用同一个Symbol值,可以用Symbol.for(),接受一个字符串作为参数,搜索有没有该参数做为名称的Symbol值,有就返回这个值,否则就新建
let s1 = Symbol.for("str");
let s2 = Symbol.for("str");
s1 === s2; // true
11-Symbol.keyFor()返回一个已登记的Symbol类型值的key
let s1 = Symbol.for("str");
console.log(Symbol.keyFor(s1)); // "foo"
let s2 = Symbol("str");
console.log(Symbol.keyFor(s2)); // undefined
实现
(function() {
var root = this;
// 9-作为标识符,可用于对象属性名,而且唯一性
var generateName = (function(){
var postfix = 0;
return function(descString) {
postfix++;
return "@@" + descString + "_" + postfix
}
})();
var SymbolPolyfill = function Symbol(description) {
// 2-不能调用new命令
// 3-instanceof结果为false,因为不能通过new的方式实现
if(this instanceof SymbolPolyfill) throw new TypeError("Symbol is not a constructor");
// 5-参数是个对象就转成字符串
var descString = description === undefined? undefined : String(description);
var symbol = Object.create({
toString: function() {
return this._Name_;
},
// 6-不能与其它类型的值进行运算
// 以+操作符为例,当进行隐式类型转换的时候,会先调用对象的valueOf方法,如果没有返回基本值,
// 就会再调用toString方法,所以要在valueOf方法中进行报错
valueOf: function() {
throw new Error("Cannot convert a Symbol value");
}
});
Object.definedProperties(symbol, {
'_Description_' : {
value: descString,
writable: false,
enumerable: false,
configurable: false
},
'_Name_': {
value: generateName(descString),
writable: false,
enumerable: false,
configurable: false
}
});
// 6-返回一个新对象,只要引用不同,就不会相同
return symbol;
}
var forMap = {};
Object.defineProperties(SymbolPolyfill, {
// 10-希望重新使用相同一个Symbol值,利用Symbol.for()传入一个参数,有就返回,否则新建
// 类似函数记忆,建立一个对象,用来存储已经创建的Symbol值
'for': {
value: function(description) {
var descString = description === undefined ? undefined : String(description)
return forMap[descString] ? forMap[descString] : forMap[descString] = SymbolPolyfill(descString);
},
writable: true,
enumerable: false,
configurable: true
},
// 11-Symbol.keyFor()方法返回一个已登记的Symbol类型的key
// 遍历forMap,查找该值对应的键值即可
'keyFor': {
value: function(symbol) {
for (var key in forMap) {
if (forMap[key] === symbol) return key;
}
},
writable: true,
enumerable: false,
configurable: true
}
});
root.SymbolPolyfill = SymbolPolyfill;
}())
1-typeof,结果为”symbol”
不能实现,并不能修改typeof操作符4-在控制台显示Symbol实例的时候,显示字符串
不能实现,模拟的是对象,无法通过调用原生console.log()打印出字符串7-Symbol值显式转为字符串
不能实现,因为在实现上存在第8点冲突了,模拟的所谓Symbol值其实是一个有着toString方法的对象,当对象作为对象属性名的时候,进行了隐式类型转换,还是会调用toString方法,出现相同的属性名;为了不会出现相同的属性名,要返回的是一个唯一值,需要修改toString方法,就命名为 generateName,我们将该唯一值添加到返回对象的 Name 属性中保存下来9-里面的遍历属性的方法
不能实现
微信公众号:**游戏机室
**