ES6躬行记(6)——Symbol

简介:   本节将会重点分析ES6引入的第6种基本类型:Symbol(符号)。符号可以像字符串那样作为对象的属性名,只是它有唯一性的特点,可以避免属性名之间的冲突。

一、创建


  符号没有字面量形式,只能通过Symbol()函数创建。该函数有一个可选的参数,只是用来描述当前符号,除了便于阅读之外,没有其他用途。由此可知,即使两个符号的描述相同,它们还是不能画等号。注意,Symbol()不是构造函数,因此不能和new运算符组合使用,否则会抛出类型错误。下面用一个例子展示符号的创建。

var sym1 = Symbol(),
  sym2 = Symbol("name"),
  sym3 = Symbol("name"),
  sym4 = new Symbol();         //抛出类型错误
console.log(sym2 === sym3);    //false

  如果要识别一个变量是否为符号,可以用typeof运算符。ES6扩展了它,当检测到符号时,能返回一个新的类型字符串“symbol”,具体如下所示。

typeof sym1;        //"symbol"
typeof sym2;        //"symbol"


二、类型转换


  符号在类型转换时表现得并不灵活,它无法与数字或字符串进行运算,也无法显式的转换成数字。如下所示,后面四条语句在执行时都会报错。

var sym = Symbol("age");
Number(sym);
parseInt(sym);
1 + sym;
"" + sym;

  不过,符号可以显式的转换成字符串或布尔值,具体如下所示。

Boolean(sym);      //true
!sym;              //false
sym.toString();     //"Symbol(age)"
String(sym);        //"Symbol(age)"


三、全局共享


  ES6会在内部维护一张全局符号注册表,通过Symbol.for()方法,可以登记指定符号,使其变成一个全局有效地符号,从而达到全局共享。该方法只接收一个参数,这个参数既是注册表中的键值,同时也是此符号的描述。下面的代码调用了两次Symbol.for()方法,传递了相同的参数,返回的却是同一个全局符号。

var sym1 = Symbol.for("name"),
  sym2 = Symbol.for("name");
console.log(sym1 === sym2);        //true

  在上面的代码中,第一次调用Symbol.for()方法时,会在注册表中搜索键值为“name”的符号,由于没有找到,所以就会创建一个新的符号。而在第二次调用Symbol.for()方法时,由于传递的键值与前一次相同,因此会返回刚刚的那个符号。从而可知,对变量sym1和sym2进行全等比较,返回的结果将是true。

  如果要获取某个全局符号所对应的键值(即它的描述),那么可以通过Symbol.keyFor()实现,具体操作如下所示。

Symbol.keyFor(sym1);    //"name"
Symbol.keyFor(sym2);    //"name"

四、属性名


  本节开头曾提到过对象的属性名可以用符号表示,而这类属性可以有三种赋值方式。第一种是用方括号,注意,不能用点号,因为点号后面的标识符会被识别成字符串而不是符号。下面代码分别用方括号和点号为obj对象的sym属性赋值,前者被识别成了符号属性,而后者却被识别成了字符串属性。

var sym = Symbol("name"),
  obj = {};
obj[sym] = "strick";
obj.sym = "strick";
console.log(obj);        //{Symbol(name): "strick", sym: "strick"}

  第二种是在创建对象字面量时,用计算属性名的方式(即属性名被方括号包裹)为其赋值,如下所示。

obj = {
  [sym]: "freedom"
};

  第三种是调用Object.defineProperty()或Object.defineProperties()方法来为符号属性赋值,如下所示。

Object.defineProperty(obj, sym, { value: "justice" });

  注意,符号属性是不可枚举的,既不能被for-in等循环遍历到,也不能被Object.keys()、Object.getOwnPropertyNames()等方法读取到。但可以通过Object.getOwnPropertySymbols()方法获得对象的符号属性,具体如下所示。


obj = {
  [sym]: "freedom",
  age: 28
};
Object.keys(obj);                   //["age"]
Object.getOwnPropertyNames(obj);      //["age"]
Object.getOwnPropertySymbols(obj);    //[Symbol(name)]


五、内置符号


  ES6提供了一些内置符号,也叫做知名符号(Well-Known Symbol)。它们暴露了语言的内部逻辑,允许开发人员修改或拓展规范所描述的对象特征或行为。每一个内置符号对应Symbol对象的一个属性,例如Symbol.hasInstance、Symbol.iterator等,表1列出了11个内置符号。

表1  内置符号

属性名称 值类型 描述
hasInstance 方法 当使用instanceof运算符时会调用该方法
isConcatSpreadable 布尔值 当对象作为Array.prototype.concat()方法的参数时,控制该对象是否被展开
iterator 方法 返回一个迭代器,用于定义一个可迭代的对象
match 方法 当对象作为String.prototype.match()方法的参数时,该方法会被调用
replace 方法 当对象作为String.prototype.replace()方法的参数时,该方法会被调用
search 方法 当对象作为String.prototype.search()方法的参数时,该方法会被调用
split 方法 当对象作为String.prototype.split()方法的参数时,该方法会被调用
species 方法 创建派生类的构造函数
toPrimitive 方法 当对象需要转换成原始值(即执行ToPrimitive抽象操作)时,该方法会被调用
toStringTag 字符串 指定对象的类型,可在调用Object.prototype.toString()方法的时候返回
unscopables 对象 保存在这个对象中的属性将不能被with语句所引用



  下面会给出4个内置符号的示例,分别是hasInstance、isConcatSpreadable、match和toStringTag。


let digit = {
  [Symbol.hasInstance](number) {
    return !(number % 2);        //判断数字是否为偶数
  }
};
1 instanceof digit;    //false
2 instanceof digit;    //true
let arr1 = [3, 4];
[1, 2].concat(arr1);             //[1, 2, 3, 4]
let arr2 = [3, 4];
arr2[Symbol.isConcatSpreadable] = false;    //禁止展开
[1, 2].concat(arr2);             //[1, 2, [3, 4]]
let regex = {
    [Symbol.match](str) {
      return str.substr(0, 10);
    }
  },
  message = "My name is strick";
message.match(regex);          //"My name is"
let people = {
  [Symbol.toStringTag]: "People"
};
people.toString();             //"[object People]"



相关文章
|
1月前
ES6之Symbol
ES6之Symbol
|
3月前
|
JavaScript 前端开发
|
3月前
|
JavaScript 前端开发 开发者
|
30天前
|
JavaScript
js开发:请解释什么是ES6的Symbol,以及它的用途。
ES6的Symbol数据类型创建唯一值,常用于对象属性键(防冲突)和私有属性。示例展示了如何创建及使用Symbol:即使描述相同,两个Symbol也不等;作为对象属性如`obj[symbol1] = 'value1'`;也可作枚举值,如`Color.RED = Symbol('red')`。
|
3月前
|
JavaScript 前端开发
ES6之原始数据类型Symbol
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它属于 JavaScript 语言的原生数据类型之一,其他数据类型是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、大整数(BigInt)、对象(Object)。Symbol的作用是创建一个不可变且唯一的标识符,可以用作对象属性的键。它可以用来解决属性名冲突的问题,避免命名冲突。
34 0
|
7月前
ES6: Symbol概念与用法举例
ES6: Symbol概念与用法举例
27 0
|
8月前
|
JavaScript
es6数据类型Symbol以及es6操作数组常用的方法
es6数据类型Symbol以及es6操作数组常用的方法
58 0
|
9月前
Es6 symbol
Es6 symbol
31 0
|
9月前
|
前端开发 JavaScript
JS(第二十五课)ES6语法Symbol
JS(第二十五课)ES6语法Symbol
61 0