ES6新数据类型:Symbol

Symbol是JavaScript的第七种数据类型,是原始数据类型,表示独一无二的值。它是ES6新引入的数据类型,引入的原因在于:ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。


创建和使用Symbol()

1、创建一个symbol类型的数据时,Symbol前不可以使用new操作符,因为Symbol值不是对象,是一个值。

let s = Symbol();

2、Symbol的参数

  • 如果Symbol的参数是一个对象,就会调用该对象的toString()方法,将其转为字符串,然后才生成一个Symbol值
    const obj = {
      toString() {
        return 'sss';
      }
    };
    const s = Symbol(obj);
    console.log(s); // Symbol(sss)
  • Symbol函数的参数只是对Symbol值的描述,因此即使参数相同的两个Symbol函数的返回值是不同的
    let s1 = Symbol();
    let s2 = Symbol();
    console.log(s1 === s2); // false
    
    let s1 = Symbol('foo');
    let s2 = Symbol('foo');
    console.log(s1 === s2); // false

3、Symbol值不能与其他类型的值运算

let s = Symbol('s is a data');
console.log(s + "Symbol");   // TypeError: can't convert symbol to string

4、Symbol值转化为其他类型

  • 转为字符串
    let s = Symbol('My symbol');
    console.log(String(s)); // 'Symbol(My symbol)'
    console.log(toString(s)); // 'Symbol(My symbol)'
  • 转为布尔值,但不可以转为数字
    let s = Symbol();
    console.log(Boolean(s)); // true
    console.log(!s);  // false
    console.log(Number(s));  // TypeError

5、ES2019提供了一个实例属性description,直接返回Symbol的描述

const s = Symbol('symbol');
console.log(s.description);  //symbol

6、由于每一个symbol值都不相同,Symbol值可以作为标识符,用于对象的属性名。

let mySymbol1 = Symbol();
let mySymbol2 = Symbol();
let mySymbol3 = Symbol();

//三种写法
let obj = {
    [mySymbol1]:"red"
};

obj[mySymbol2] = 'green';

Object.defineProperty(obj, mySymbol3, { value:"blue" });
  •  不可以使用点运算符
    const mySymbol = Symbol();
    const obj = {};
    
    obj.mySymbol = 'point';
    console.log(obj[mySymbol]); // undefined
    console.log(obj['mySymbol']); // "point"
  • 在对象内部定义属性要使用[],如果Symbol值不放在[]中,该属性名就是字符串,而不是Symbol值了
    let s = Symbol();
    let obj = {
      [s]: function (arg) { ... }
    };
    obj[s](123);

几个相关的方法

遍历对象时Symbol作为属性名不会出现在for..in、for..of循环,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。但它并非私有属性。

  1. 获取指定对象的所有Symbol属性名:Object.getOwnPropertySymbols()。当前对象的所有用作属性名Symbol值以数组的形式被该方法返回。
    const obj = {};
    let a = Symbol('a');
    let b = Symbol('b');
    obj[a] = 'red';
    obj[b] = 'blue';
    
    console.log(Object.getOwnPropertySymbols(obj));  //[Symbol(a), Symbol(b)]

    对比for..in循环与Object.getOwnPropertyNames():这两种方法都无法得到Symbol属性名

    const obj = {};
    const s = Symbol('sss');
    obj[s] = 'yyy';
    
    for (let i in obj) {
      console.log(i); // 无输出
    }
    
    console.log(Object.getOwnPropertyNames(obj)); // []
    
    consoel.log(Object.getOwnPropertySymbols(obj)); // [Symbol(sss)]
    
  2.  Reflect.ownKeys()。返回所有类型的键名,包括常规键名和Symbol键名。
    let obj = {
      [Symbol('s')]: 1,
      enum: 2,
      nonEnum: 3
    };
    
    console.log(Reflect.ownKeys(obj));//  ["enum", "nonEnum", Symbol(s)]
    
  3. Symbol.for() 。接收一个字符串作为参数,搜索是否有以该参数作为名称的Symbol值。有就返回这个Symbol值,否则就新建一个以该字符串为名称的Symbol值,并将其注册到全局。
    let s1 = Symbol.for('foo');
    let s2 = Symbol.for('foo');
    
    console.log(s1 === s2); // true
    

     上面这个栗子中,s1是通过Symbol.for()创建的,因此可知,Symbol.for()和Symbol()这两种写法,都会生成新的 Symbol。区别在于:

    Symbol.for(),会被登记在全局环境中以供搜索 ,不会每次调用都返回一个新的Symbol类型的值。

    Symbol(),不会登记在全局环境中,每次调用都会创建一个新的Symbol类型的值。 

    consol.log(Symbol.for("bar") === Symbol.for("bar"));  // true
    console.log(Symbol("bar") === Symbol("bar"));  // false
    
    
    let s1 = Symbol.for("s");
    console.log(Symbol.keyFor(s1)); // s
    let s2 = Symbol("s");
    console.log(Symbol.keyFor(s2)); // undefined
    

     Symbol.for()是为 Symbol 值登记的名字,是全局环境的,不管有没有在全局环境运行。

    function fn() {
      return Symbol.for('s');
    }
    
    const x = fn();
    const y = Symbol.for('s');
    console.log(x === y); // true
    

    Symbol.for()的这个全局登记特性,可以用在不同的 iframe 或 service worker 中取到同一个值。 

    iframe = document.createElement('iframe');
    iframe.src = String(window.location);
    document.body.appendChild(iframe);
    
    iframe.contentWindow.Symbol.for('foo') === Symbol.for('foo')
    // true
    

     上面代码中,iframe 窗口生成的 Symbol 值,可以在主页面得到。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值