symbol
一.ES6引入Symbol的原因
ES5对象属性名都是字符串,容易造成属性名的冲突。
let obj={ name:'zs'}
//为对象添加一个新的属性name
let prop = 'name'
obj[prop]='male'
console.log(obj) //{name: "male"}
//为这个对象添加新的方法,新方法的名字就有可能与现有方法产生冲突。
//如果有一种机制,保证每个属性的名字都是独一无二的,这样就从根本上防止了属性名冲突.
ES6中引入了一种新的基础数据类型:Symbol ,表示独一无二的值。
二.创建
1.Symbol 值由Symbol函数生成
let s = Symbol();
console.log(s); //Symbol()
let s = new Symbol();
console.log(s);
// Uncaught TypeError: Symbol is not a constructor
[注意]Symbol函数前不能使用new命令,否则会报错。因为生成的 Symbol 是一个原始类型的值,不是对象
2.Symbol(可选参数)
可选参数 : 描述即将创建的Symbol,建议添加,以便于阅读代码和调试Symbol程序
let obj = {};
let prop = Symbol("name");
obj[prop] = "zs";
console.log("name" in obj); // false
//Symbol的描述不能直接在代码里访问,只有当调用Symbol的toString()方法时才可以读取这个属性
console.log(prop); // Symbol(name)
console.log(obj); //{Symbol(name): "zs"}
//在执行console.log()时隐式调用了prop的toString()方法
3.类型检测
使用typeof检测数据类型时,返回一个属于自己的类型symbol,symbol是基础数据类型
let s1 = Symbol();
console.log(typeof s1); //symbol
4.每个Symbol实例都是唯一的
let s1 = Symbol()
let s2 = Symbol('name')
let s3 = Symbol('name')
s1 === s2 // false
s2 === s3 // false
5.不能将Symbol强制转换成数字类型或者字符串类型
let name = Symbol('name')
console.log(name + "");
//Uncaught TypeError: Cannot convert a Symbol value to a string
let id = Symbol('id')
console.log(id * 1)
//Uncaught TypeError: Cannot convert a Symbol value to a number
let name = Symbol('name')
console.log(String(name)) //'Symbol(uid)'
//通过String(),可以将Symbol转化为字符串类型
三.Symbol值的应用场景
1.作为对象的属性名
凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突
let name = Symbol('name');
let obj = {name:'zs'};
obj[name]='ls'
console.log(obj) //{name:'zs',Symbol(name):'ls'}
console.log(obj.name); // "zs"
console.log(obj[name]); // "ls"
[注意]Symbol 值作为对象属性名时,不能用点运算符
let name = Symbol('name');
let obj = {};
//obj添加了一个Symbol()创建的属性:"Symbol('name')"
obj[name]='male'
console.log(obj); //{Symbol(name): "male"}
console.log(obj[name]); //"male"
console.log(obj.name) //undefined(没有name这个属性)
遍历用Symbol()生成的对象属性
通常遍历对象的属性:Object.keys()或者for...in 或者Object.getOwnPropertyNames(obj)
let obj = {
[Symbol('name')]: 'zs',
age: 18,
sex: 'male'
}
console.log(Object.keys(obj)); // ['age', 'sex']
for (let k in obj) {
console.log(k) // 分别会输出:'age' 和 'sex'
}
console.log(Object.getOwnPropertyNames(obj)); // ['age', 'sex']
//通常遍历对象属性的方法,无法遍历symbol类型的对象属性
遍历用Symbol()生成的对象属性:Object.getOwnPropertySymbols(obj)或者 Reflect.ownKeys(obj)
// 使用Object的API(只能遍历symbol类型的对象属性)
Object.getOwnPropertySymbols(obj) // [Symbol(name)]
// 使用新增的反射API(所有的对象都可以遍历)
Reflect.ownKeys(obj) // [Symbol(name), 'age', 'title']
2.使用Symbol来替代常量
3.使用Symbol定义类的私有属性/方法
使用Symbol来定义的类属性是没有办法被模块外访问到的,达到了一个私有化的效果。
四.注册和获取全局Symbol
Symbol.for()
首先在全局中搜索有没有以该参数作为名称的Symbol值,如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值
let s1 = Symbol.for('name');
let s2 = Symbol.for('name');
s1 === s2 // true
//它们都是同样参数的Symbol.for方法生成的,所以实际上是同一个值。
Symbol.keyFor()
Symbol.keyFor方法返回一个已登记的Symbol类型值的key。实质就是检测该Symbol是否已创建
let s1 = Symbol.for("name");
Symbol.keyFor(s1) // "foo"
let s2 = Symbol("name");
Symbol.keyFor(s2) // undefined
//Symbol()写法没有登记机制,变量s2属于未登记的Symbol值,所以返回undefined
ES6引入Symbol数据类型以避免属性名冲突。Symbol值由函数生成,每个实例都是唯一的,不可转换为数字或字符串。它常用于创建独一无二的对象属性名,替代常量,以及定义类的私有属性/方法。通过Symbol.for()注册和获取全局Symbol,并用Symbol.keyFor()检查已创建的Symbol。
2149

被折叠的 条评论
为什么被折叠?



