Symbol

ES6引入Symbol数据类型以避免属性名冲突。Symbol值由函数生成,每个实例都是唯一的,不可转换为数字或字符串。它常用于创建独一无二的对象属性名,替代常量,以及定义类的私有属性/方法。通过Symbol.for()注册和获取全局Symbol,并用Symbol.keyFor()检查已创建的Symbol。

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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值