Symbol的基本使用

Symbol的介绍

        ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是Javascript语言的第七种数据类型。

        ES5对象属性名都是字符串,这容易造成属性名的冲突。为了解决这个问题引入了Symbol类型来解决命名冲突的问题。

        Symbol值通过Symbol函数生成,也就是说,对象的属性名现在可以有两种形类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。

Symbol的特点

  1. Symbol的值是唯一的,用来解决命名冲突的问题
  2. Symbol值不能与其他数据进行运算
  3. Symbol定义的对象属性不能使用for.in循环遍历,但是可以使用Reflect.ownkeys来获取对象的所有键名 

认识Symbol

 Symobol函数可以接受一个字符串作为参数,用来区分或者描述Symbol实例。

// 创建Symbol
let x = Symbol('abc')
let y = Symbol('123')
console.log(x, y);   // Symbol(abc) Symbol(123)

如果Symbol的参数传递的是一个对象,那么它内部会调用toString方法将对象转为字符串,在生成一个Symbol值。

// 参数传递对象
let a = Symbol({a: "a"})
console.log(a);     // Symbol([object Object])

相同参数创建出来的Symbol值是不相等的

// 相同参数不相等
let b = Symbol("1");
let c = Symbol("1");
console.log(b === c)   // false
let d = Symbol();
let e = Symbol();
console.log(d === e)   // false

Symbol的值不能与其他类型的值进行运算,如果进行运算会报错。

// 不能与其他类型的值进行运算
let n = Symbol("hello")
console.log(n + "world");  // Uncaught TypeError: Cannot convert a Symbol value to a string

Symbol可以显示转为字符串。

// Symbol显示转为字符串
let f = Symbol("hello wrold")
console.log(f.toString());    // Symbol(hello wrold)
console.log(typeof f.toString());    // string

Symbol也可以转为Boolean值

// Symbol也可以转为Boolean值
let g = Symbol("hello wrold")
console.log(Boolean(g));   // true

Symbol作为对象的属性名

        前面我们说到每一个Symbol的值都是不相等的,所以我们可以将Symbol的值作为对象的属性名来使用,这样就能保证不会出现同名属性,防止属性被覆盖或者改写。

// 将Symbol作为对象的属性名使用
let sym = Symbol('sym'),
    sym1 = Symbol('sym1'),
    sym2 = Symbol('sym2');
const obj = {
    [sym]: "hello",
}
obj[sym1] = "world"
Object.defineProperty(obj, sym2, {value: "!!!!"})
console.log(obj);  // {Symbol(sym): 'hello', Symbol(sym1): 'world', Symbol(sym2): '!!!!'}
console.log(obj[sym], obj[sym1] ,obj[sym2]);    // hello world !!!!
const fun = Symbol('fun');
const obj1 = {
    [fun] () {
        console.log('hello world!');
    }
}
obj1[fun]()  //hello world!

Symbol属性名的遍历

        Symbol 作为属性名,该属性不会出现在for in、for of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()返回。但是它也不是私有属性,有一个Object.getOwnPropertySymbols()方法可以获指定对象的所有Symbol属性名。

        Object.getOwnPropertySymbols()方法返回的是一个数组,成员是当前对象所有用作属性名的Symbol值

        Reflect.ownKeys()方法返回所有类型的键名,包括常规键名和Symbol键名。

const a = Symbol('a')
const b = Symbol('b')
const obj = {
    a: 'a',
    b: 'b',
    [a]: 'a',
    [b]: 'b'
}
// // 返回当前对象所有用作属性名的Symbol值
const objSymbols = Object.getOwnPropertySymbols(obj)
console.log(objSymbols);   // [Symbol(a), Symbol(b)]
// 返回对象内所有类型的键名
const objSymbols1 = Reflect.ownKeys(obj)
console.log(objSymbols1);   // ['a', 'b', Symbol(a), Symbol(b)]

Symbol.for() 、Symbol.keyFor()

        有时候我们想要使用同一个Symbol值,Symbol.keyFor()方法可以做到这一点。它接收一个字符串参数,让后搜索有没有以该参数作为名称的Symbol值,如果有,就返回这个Symbol值,否则就新建一个以该字符串命名的Symbol值。

// 同样参数使用Symbol.for方法生成的值相同
let sym = Symbol.for('a');
let sym1 = Symbol.for('a');
console.log(sym === sym1);    // true

        Symbol.for()和Symbol()这两种写法都会生成新的Symbol,它们的区别是,前者会被登记在全局环境中供搜索,而后者不会Symbol.for(),不会在每次调用时都返回一个新的Symbol类型的值,而是先检查给定的key是否已经存在,如果不存在就会返回一个新值。

Symbol.keyFor()方法返回一个已登记的Symbol类型值的key

let sym = Symbol.for('a');
let sym1 = Symbol('a');
console.log(Symbol.keyFor(sym));   // 'a'
console.log(Symbol.keyFor(sym1));  // undefined

sym1属于为登记的Symbol值,所以返回undefined

注意:Symbol.for()方法为Symbol方法登记的名字是全局的。

内置的Symbol

        除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。

        以下属性不一一举例说明了,如果需要详细示例请看ECMAScript 6 标准入门icon-default.png?t=L9C2https://es6.ruanyifeng.com/#docs/symbol

Symbol.hasInstance

        对象的Symbol.hasInstance属性,指向一个内部方法。当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法。比如,foo instanceof Foo在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)

class MyClass {
  [Symbol.hasInstance](foo) {
    return foo instanceof Array;
  }
}
[1, 2, 3] instanceof new MyClass() // true

        上面代码中,MyClass是一个类,new MyClass()会返回一个实例。该实例的Symbol.hasInstance方法,会在进行instanceof运算时自动调用,判断左侧的运算子是否为Array的实例。

Symbol.isConcatSpreadable

        对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。

Symbol.species

对象的Symbol.species属性,指向一个构造函数。创建造衍生对象时,会使用该属性。

 

Symbol.match

对象的Symbol.match属性,指向一个函数。当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值。

Symbol.replace

对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。

Symbol.search

对象的Symbol.search属性,指向一个方法,当该对象被String.prototype.search方法调用时,会返回该方法的返回值。

Symbol.split

对象的Symbol.split属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值。

Symbol.iterator

对象的Symbol.iterator属性,指向该对象的默认遍历器方法。

Symbol.toPrimitive

对象的Symbol.toPrimitive属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。

Symbol.toPrimitive被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式。

  • Number:该场合需要转成数值
  • String:该场合需要转成字符串
  • Default:该场合可以转成数值,也可以转成字符串

Symbol.toStringTag

对象的Symbol.toStringTag属性,指向一个方法。在该对象上面调用Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制[object Object][object Array]object后面的那个字符串。

Symbol.unscopables

对象的Symbol.unscopables属性,指向一个对象。该对象指定了使用with关键字时,哪些属性会被with环境排除。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李公子丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值