Symbol----ES6学习笔记

ES5中有6种数据类型:

Number(数值),String(字符串),Boolean(布尔值),Object(对象),
undefinednull

ES6新引入了一种数据类型(Symbol):

ES5中对象的属性名都是字符串类型,这样可能会导致属性名的冲突,比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。这时使用Symbol作为属性名,就可以解决冲突。

ES6引入了一种新的数据类型(Symbol),表示独一无二的值。

  let text = Symbol();
  
  typeof text;  //Symbol

重点 : Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。

Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述。

   let text = Symbol("hello");
   
   text             //Symbol(hello)
   text.toString(); //"Symbol(hello)"
   String(text);    //"Symbol(hello)"

如果不加字符串(String)作为参数,那么每一个Symbol数据类型的实例输出都是Symbol(),不利于区分。

注意,Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的(Symbol表示独一无二的值)。

  let sym1 = Symbol("bar");
  let sym2 = Symbol("bar");

  sym1 === sym2  //false

上面的例子中,sym1sym2都是Symbol函数的返回值,而且参数相同,但是sym1sym2是不相等的。

Symbol值不能与其他数据类型的值进行运算。

   let sym = Symbol("hello");
   sym + 1;  //TypeError: can't convert symbol to number
1.Symbol.prototype.description

Symbol.prototype.description返回 Symbol 的描述,descriptionSymbol 实例的属性。

  let sym = Symbol("hello");
  
  sym.description  //"hello"

2.Symbol作为对象的属性值

由于每一个symbol的值都是独一无二的。所以可以用symbol的值作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。

  let sym = Symbol();
 
  //第一种写法:
  let a = {};
  a[sym] = "hello";
  a[sym] //"hello"

  //第二种写法:
  let a{
       [sym]:"hello";
     }
  a[sym]  //"hello"
  
  // 第三种写法
  let a = {};
  Object.defineProperty(a, sym, { value: 'Hello!' });

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

    let a = {};
    let sym = Symbol();
    a.sym = "hello";

    a[sym]   //undefined
    a["sym"] //"hello"

a.sym 点运算符会将sym识别成字符串"sym",而不是Symbol 值,所以访问a[sym]的值为undefined

同理,在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中,否则将会被识别为字符串。

  let sym = Symbol();
  let b{
     [sym]:"i am Symbol",
     sym:"i am String"
  }
 console.log(b[sym]);  //"i am Symbol"
 console.log(b.sym);   //"i am String"
3.属性名的遍历

for…infor…ofObject.keys()Object.getOwnPropertyNames()JSON.stringify()取不到值为Symbol的属性名。

Object.getOwnPropertySymbols()方法,可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。

    let sym1 = Symbol("foo");
    let sym2 = Symbol("bar");
    let a = {
        [sym1]:"first",
        [sym2]:"second"
    }
    
    Object.getOwnPropertySymbols(a);//Array [ Symbol(foo), Symbol(bar) ]

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

    let sym1 = Symbol("foo");
    let sym2 = Symbol("bar");
    let a = {
        [sym1]:"first",
        [sym2]:"second",
        name:"shishuo",
        age:"43"
    }
    Reflect.ownKeys(a);//Array(4) [ "name", "age", Symbol(foo), Symbol(bar) ]

上面的例子可以看出Reflect.ownKeys()方法返回一个数组,数组成员是参数对象的所有类型的属性名(常规键名+Symbol键名)


4.Symbol.for()与Symbol.keyFor()

Symbol.for()方法,接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。

    let sym1 = Symbol.for("foo");  //搜索有没有名字为foo的Symbol值,没有,新建一个symbol,名字为foo
    let sym2 = Symbol.for("foo");  //搜索有没有名字为foo的Symbol值,有,返回它
    
    sym1 === sym2  //true

注意:Symbol.for()新建的Symbol值是注册到全局的。(只要是通过Symbol.for()创建的Symbol,都是全局范围内的值)

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

function foo() {
  return Symbol.for('bar');
}

const x = foo();
const y = Symbol.for('bar');
console.log(x === y); // true

上面代码中,Symbol.for(‘bar’)是函数内部运行的,但是生成的 Symbol 值是登记在全局环境的。所以,第二次运行Symbol.for(‘bar’)可以取到这个 Symbol 值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值