0


JS(6).Symbol详细介绍

(一)、引出symbol

  • 在ES5中,对象的属性名都是字符串,这容易造成属性名的冲突(比如,在模块化应用中,如果你使用了一个其他人提供的对象,同时你又想为这个对象添加新的属性,这个新的属性的名字,就有可能和原来的对象中的属性名发生冲突,导致覆盖产生,如下面的例子:)
let a ={x:1,y:2}
a['x']=2
console.log(a)//{x:2,y:2}
  • 如果存在一种机制,保证每个属性的名字都是独一无二的,这样就能够防止属性的冲突了。这便是ES6引入Symbol的原因了

(二)、Symbol介绍

1、Symbol()

  • ES6引入了Symbol,它为原始数据类型,表示独一无二的值
  • Symbol通过Symbol函数生成(注意:Symbol为原始数据类型,不能使用new命令)
let s1 =Symbol()let s2 =Symbol()

console.log(s1===s2)//false
console.log(typeof s1)//'symbol'

2、Symbol()的参数

  • Symbol函数也可以接收一个字符串作为参数,表示对Symbol实例的描述,这样做的目的是利于区分:
  • 注意:Symbol()的参数只是表示对于当前Symbol值得描述,因此相同参数的Symbol的返回值是不相等的
//s1和s2都是Symbol值,如果不加参数,它们的输出都是Symbol,不利于区分let s1 =Symbol()let s2 =Symbol()

console.log(s1)//Symbol
console.log(s2)//Symbol//参数只是一种描述,相同参数时,两个Symbol()的返回值并不相等let s3 =Symbol('foo')letS4=Symbol('foo')

console.log(s3)//Symbol(foo)
console.log(s4)//Symbol(foo)
console.log(s3 === s4)//false

3、Symbol作为对象中的属性名:

  • ES6引入Symbol后,对象中的属性名现在可以有两种,一种是本来就有的字符串,另一种则是新增的Symbol类型。
  • 由于每个Symbol值都是不同的,这就意味着,当一个对象由模块构成时,就能够发防止莫一个键被不小心改写或覆盖
let a ={x:1,y:2}let x =Symbol()
a[x]='hello'

console.log(a)

在这里插入图片描述

  • 注意:Symbol值作为对象属性时,不能使用点运算符,因为点运算符后面接的是字符串。只能使用中括号,因为中括号内接表达式
let a ={}let x =Symbol()
a[x]='hello'

console.log(a[x])//hello
console.log(a.x)//undefined

4、属性名的遍历

  • Symbol 作为属性名,该属性不会出现在 for…in 、 for…of 循环中,也不会被 Object.keys() 、 Object.getOwnPropertyNames() 、 JSON.stringify() 返回。但是,它也不是私有属性,有一个 Object.getOwnPropertySymbols 方法,可以获取指定对象的所有Symbol 属性名(以数组形式排列)。
let a ={x:1,y:2}let x =Symbol()
a[x]='hello'for(key in a){
    console.log(key,a[key])/*
        x 1
        y 2
    */}

console.log(Object.getOwnPropertySymbols(a))//[Symbol()]

5、Symbol.for()

  • 我们希望重新使用同一个 Symbol 值, Symbol.for 方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。
let s1 = Symbol.for('foo')let s2 = Symbol.for('foo')
console.log(s1===s2)//true

6、Symbol()和Symbol.for()的区别、以及Symbol.keyfor()

  • Symbol()每次被调用都会生成一个新的Symbol(一位内Symbol(写法没有登记机制,所以每次调用都会返回一个不同的值)
  • Symbol.for()不会每次调用就返回一个新的Symbol,而是会先检查给定的key是否已经存在,如果不存在,则会在全局创建并注册这个key,然后才会新建一个Symbol值
  • Symbol.keyFor()方法返回一个已经登记的Symbol类型值的key
let s1 = Symbol.for("foo");
Symbol.keyFor(s1)// "foo"let s2 =Symbol("foo");
Symbol.keyFor(s2)// undefined

7、内置的Symbol值

  • 7.1、Symbol.hasInstance
  • 该属性可以表示一个方法:Symbol.hasInstance,这个方法表示一个构造器对象是否认可一个对象是它的实例。通俗点来说,就是干了instanceof的事情
functionFoo(){}let f =newFoo()
console.log(f instanceofFoo);//true
console.log(Foo[Symbol.hasInstance](f))//true
  • 7.2、Symbol.isConcatSpreadable
  • 对象的 Symbol.isConcatSpreadable 属性等于一个布尔值,表示该对象用于 Array.prototype.concat() 时,是否可以展开。
let arr1 =['c','d'];['a','b'].concat(arr1,'e')// ['a', 'b', 'c', 'd', 'e']
arr1[Symbol.isConcatSpreadable]// undefinedlet arr2 =['c','d'];
arr2[Symbol.isConcatSpreadable]=false;['a','b'].concat(arr2,'e')// ['a', 'b', ['c','d'], 'e']
  • 7.3、Symbol.match
  • 相当于String.prototype.match()方法使用,即用正则表达式去匹配字符串
String.prototype.match(regexp)// 等同于
regexp[Symbol.match](this)
  • 7.4、Symbol.toPrimitive
  • 该属性指向一个方法,该方法表示将对象转换为相应的原始值
  • 很多内置操作都会强制将对象转换为原始值,包括字符串,数值和未指定的原始类型
  • Symbol.toPrimitive被调用时(即被内置操作强制转换时),会接受一个字符串参数(hint),表示当前运算的模式,一共有三种模式。
    • Number:该场合需要转成数值
    • String:该场合需要转成字符串
    • Default:该场合可以转成数值,也可以转成字符串
let obj ={[Symbol.toPrimitive](hint){switch(hint){case'number':return123;case'string':return'str';case'default':return'default';default:thrownewError();}}};//内置操作 2*obj,强制将obj转换为数值类型2* obj // 246//内置操作 3+obj, 这种情况,既可以将obj转换为数值也可以转换为字符串3+ obj // '3default'

obj =='default'// true//String(obj),将obj转换为字符串String(obj)// 'str'

本文转载自: https://blog.csdn.net/wsz123456wsz/article/details/127598604
版权归原作者 万人之英 所有, 如有侵权,请联系我们删除。

“JS(6).Symbol详细介绍”的评论:

还没有评论