ES6学习day04

今天学习Symbol


一、Symbol

1.概述

   在ES5中对象的属性名都是字符串,这就很容易出现命名冲突。当你引用了别人定义的对象,但你又想对这个对象添加新的方法,那么新的方法和旧的方法可能就会产生冲突。
   这种情况下,如果有一种机制保证每个对象的属性名都是独一无二的就好了,这样就可以从根本上阻止命名冲突,这也就是ES6引入Symbol的原因。
   ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。Symbol是JavaScript中的第七种数据类型,这七种分别是数值(Number)、字符串(String)、布尔值(Boolean)、空(Null)、未定义(undefined)、对象(Object)、Symbol。

2.Symbol的创建

symbol可以通过Symbol函数来创建,但是Symbol函数前不能使用new命令。我们要了解到Symbol是一种新的原始数据类型,而使用new命令创建的是一个对象,所以Symbol函数前不能使用new命令。

let s=Symbol('this is a Symbol');
console.log(typeof s);//symbol

可以看到,typeof运算符的结果表明变量s是Symbol数据类型,而不是其他的数据类型。
Symbol不是对象,所以也无法添加属性,Symbol是一种类似字符串的数据类型。
Symbol可以接收一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者在转换为字符串时比较容易区分。

let s1=Symbol('firstSymbol');
let s2=Symbol('secondSymbol');
console.log(s1);//Symbol(fristSymbol)
console.log(s2);//Symbol(secondSymbol)
console.log(s1.toString());//"Symbol(fristSymbol)"
console.log(s2.toString());//"Symbol(secondSymbol)"

如果Symbol的参数是一个对象时,就会调用该对象的toString方法,将其转为字符串,然后才生成一个Symbol值。

const obj={
  a:'123'
}
console.log(obj.toString());//[object Object]
const sym=Symbol(obj);
console.log(sym);//Symbol([object Object])
const obj2={
  toString(){
    return '我是obj的toString()方法';
  }
}
const sym2=Symbol(obj2);
console.log(sym2);//Symbol(我是obj的toString()方法)

要注意,前面提到了Symbol代表一个独一无二的值,而Symbol函数的参数只是表示对当前Symbol值的描述对值不产生影响,因此相同参数的Symbol函数的返回值也是不相等的。

// 没有参数的情况下
let s1=Symbol();
let s2=Symbol();
console.log(s1===s2);//false

// 参数不相同的情况下
let q1=Symbol('man');
let q2=Symbol('women');
console.log(q1===q2);//false

// 参数相同的情况下
let e1=Symbol('same');
let e2=Symbol('same');
console.log(e1===e2);//false

要注意,Symbol类型的值不能与其他类型的值进行运算,否则会报错。

let s1=Symbol('im a symbol');
let str='im a str';
s1+str;//TypeError:Cannot convert a Symbol value to a string

Symbol可以显示得转换为一些其他的数据类型,比如字符串(String)和布尔类型(Boolean),但是不能转为数值类型(Number)

let s1=Symbol('im a symbol');
console.log(String(s1));//"Symbol(im a symbol)"
console.log(s1.toString());//"Symbol(im a symbol)"
console.log(Boolean(s1));//true
console.log(!s1);//false
console.log(Number(s1));//TypeError: Cannot convert a Symbol value to a number
console.log(s1+1);//TypeError: Cannot convert a Symbol value to a number

3.Symbol.prototype.description

创建Symbol的时候,可以添加一个描述。
但是在读取这个描述时,需要将Symbol显示转为字符串。

let s1=Symbol('im a symbol');
console.log(String(s1));//"Symbol(im a symbol)"
console.log(s1.toString());//"Symbol(im a symbol)"

这么做很不方便,所以ES2019给Symbol的原型添加了一个属性description,直接返回Symbol的描述。

let s1=Symbol('im a symbol');
console.log(s1.description);//im a symbol

4.作为属性名的Symbol

由于每个Symbol值都是独一无二的,这意味着使用Symbol类型的值作为对象的属性名就能保证不会出现同名的属性。这对于一个对象由多个模块组成的情况非常有用,能够防止某一个键被不小心改写或覆盖。

let mySymbol=Symbol();

// 第一种写法
let a={};
a[mySymbol]='Hello!';

// 第二种写法
let b={
  [mySymbol]:'Hello!'
};

// 第三种写法
let c={};
Object.defineProperty(c,mySymbol,{value:'Hello!'});

// 以上的写法都能得到相同的结果
console.log(a[mySymbol]);//"Hello!"
console.log(b[mySymbol]);//"Hello!"
console.log(c[mySymbol]);//"Hello!"

注意Symbol值作为对象属性名时,不能用点运算符。

a.mySymbol = 'Hello!';
console.log(a[mySymbol]); // undefined
console.log(a['mySymbol'] );// "Hello!"

因为点运算符后面总是字符串,所以不会读取mySymbol作为标识名所代指的那个值,导致a的属性名实际上是一个字符串,而不是一个Symbol值。


let s1=Symbol();
let obj={
  [s1]:function(arg){console.log(arg);}
};
obj[s1](123);//123

在对象的内部,使用Symbol值定义属性时,Symbol值必须放在方括号之中。
如果Symbol值不放在方括号中,该属性的键名就是字符串s1,而不是s1所代表的那个Symbol值。
要注意一点,Symbol值作为属性名时,该属性时还是公开属性,不是私有属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值