Daily Archives: 2020年10月14日

ES6中的Symbol、Iterator、Generator的简单理解

  本来是想说说生成器Generator的,但我发现和迭代有关,所以要先讲讲迭代器Iterator,可迭代器又会扯到Symbol,所以拉出来一起说说;

Symbol

Symbol是ES6引进的一种新数据类型,它代表一个独一无二的值,至此JavaScript一共有7种数据类型,分别是:UndefindedStringSymbolObjectNullNumberboolean

Symbol是什么

Symbol到底是什么?先来个栗子看看效果:

let s1 = Symbol();
let s2 = Symbol();
console.log(s1, typeof s1); // Symbol() "symbol"
console.log(s1 === s2); // false

let s3 = Symbol('symbol');
let s4 = Symbol('symbol');
console.log(s3, s4);    // Symbol(symbol) Symbol(symbol)
console.log(s3 === s4); // false

let s5 = Symbol.for('symbol');
let s6 = Symbol.for('symbol');
console.log(s5, s6);    // Symbol(symbol) Symbol(symbol)
console.log(s5 === s6); // true
console.log(s4 === s5); // false
  • Symbol有两种创建方式,一种是Symbol(),一种是Symbol.for();
  • 注意: Symbol不是对象,不要使用new关键字;
  • Symbol()函数可接收一个字符串为参数,仅做描述使用,不代表Symbol的唯一性;
  • Symbol.for()接收一个字符串做为参数,代表Symbol的唯一性,相同的字符串能取到唯一的Symbol;

Symbol怎么用

既然Symbol的特性代表独一无二,那典型的应用场景就是需要唯一性的场所,比如说枚举值、对象的属性名或方法名等。
* 以性别为例,我们定义一个gender对象,分别有malefemale两个属性,我们在应用的时候可能只需要区分这两者不一样即可,并不关心他们实际值是多少,可以将值设置为Symbol类型。(如果需要与服务端交互另说,这里主要是为了说明Symbol的用法,勿喷)

// 性别:常规定义
const gender = {
    male: 'male',   // 男
    female: 'female'    // 女
}
// 性别:Symbol定义
const gender = {
    male: Symbol(),
    female: Symbol()
}
  • 做为对象的属性名或方法名在ES6中也已经很常见了,可查看数组的原型对象不可以找到名称为Symbol类型的方法。
  • 举例说明,假设有一个person对象,我想扩展一个方法,但又不确定新加的方法名是否会引起冲突,所以使用Symbol类型的值做为方法名
// person对象
let person = {
    name: 'yusian',
    age: 21,
    say() {
        console.log('saying...');
    }
}
// 自定义方法名
let methods = {
    say: Symbol('say'),
    run: Symbol('run')
}
person[methods.say] = function () {
    console.log('symbol saying...');
}
person[methods.run] = function () {
    console.log('symbol running...');
}
person.say();   // saying...
person[methods.say]();  // symbol saying...
person[methods.run]();  // symbol running...
  • 为什么要说Symbol类型的方法名呢,我们以后会经常使用Symbol类型的数据做为方法名来扩展对象功能吗?我觉得不应该这样,这并不是一个很好的解决方案。比较有价值的是ES6提供的内置的Symbol值
  • 重点来了 前面所有Symbol相关的点都为这一刻,以Symbol.hasInstance为例,定义一个Person类,在类中定义一个静态方法名为Symbol.hasInstance,那么当对该类进行instanceof调用时就会执行该静态方法,返回值即为调用返回结果。
class Person {
    // 方法名一般为字符串,Symbol类型做为方法名需要加方括号
    static [Symbol.hasInstance] = function (foo) {
        console.log('hasInstance, ', foo);
        return false;
    }
}
let p = new Person();
console.log(p instanceof Person);   // false
  • 大致用法就是这个样子,更多内置Symbol值参考:MDN
  • 有了这个基础后面就可以讲Iterator了

参考链接:阮一峰ES6入门
[……]

继续阅读