重温 ES6 Symbol

Symbol 是 ES6 引入的一种新的原始数据类型,表示独一无二的值。

Symbol 特性

1.Symbol 通过工厂函数创建,不能以 new 的方式创建,所以使用 instanceof 运算符返回的结果为 false

var sym = Symbol();
var sym1 = new Symbol(); // TypeError
sym instanceof Symbol // false

2.Symbol 使用 typeof 运算符返回 “symbol”

var sym = Symbol('foo');
typeof sym;     // "symbol"

3.Symbol 工厂函数能支持一个可选的参数,用于描述当前的 symbol

var sym2 = Symbol('foo');
var sym3 = Symbol('foo');

4.Symbol 是唯一的,Symbol("foo") == Symbol("foo") 返回 false

Symbol('foo') === Symbol('foo'); // false

5.Symbol 与数值或字符串进行运算时,会抛出异常

sym | 0 // TypeError
Symbol("foo") + "bar" // TypeError

6.Symbol 工厂函数返回的 symbol,可作为对象的属性名,可以避免属性冲突,在 for...in 迭代中不可枚举

var obj = {};

obj[Symbol("a")] = "a";
obj[Symbol.for("b")] = "b";
obj["c"] = "c";
obj.d = "d";

for (var i in obj) {
   console.log(i); // logs "c" and "d"
}

7.Symbol 工厂函数返回的值,可作为对象属性名,当使用 JSON.stringify() 进行序列化时,该属性会被忽略

JSON.stringify({[Symbol("foo")]: "foo"});  // '{}'

8.Symbol 是唯一的,但可以使用 Symbol.for() 共享同一个 Symbol 值

var mySymbol1 = Symbol.for('some key'); 
var mySymbol2 = Symbol.for('some key');
mySymbol1 == mySymbol2 //true

Symbol 实战

对象字面量私有属性和方法

const myPrivateMethod = Symbol("myPrivateMethod");
const myPrivateProperty = Symbol("myPrivateProperty");

const obj = {
    [myPrivateProperty]: "semlinker",

    [myPrivateMethod]() {
        return `Hello ${this[myPrivateProperty]}!!!`;
    },

    hello() {
        console.log(this[myPrivateMethod]()); 
    }
};

console.log(Object.keys(obj));
console.log(obj.hello());

除了在创建对象字面量时可以使用 Symbol 外,在定义类的私有属性和方法时也可以使用。

类的私有属性和方法

const myPrivateMethod = Symbol("myPrivateMethod");
const myPrivateProperty = Symbol("myPrivateProperty");

class MyClass {
    constructor() {
        this[myPrivateProperty] = "semlinker";
    }

    [myPrivateMethod]() {
        return `Hello ${this[myPrivateProperty]}!!!`;
    }

    hello() {
        console.log(this[myPrivateMethod]()); 
    }
}

const myCls = new MyClass();
console.log(myCls.hello());

在 ES6 中,引入了一些全局的 Symbols,比如:Symbol.match,Symbol.replace,Symbol.search,Symbol.iterator 和 Symbol.split。这里我们简单介绍一下 Symbol.search 和 Symbol.iterator。

Symbol.iterator

class Skill {
    constructor() {
        this.skills = ['Angular', 'React', 'Vue', 'Koa', 'Ionic'];
    }

    [Symbol.iterator]() {
        let index = 0;
        return {
            next: () => {
                const value = this.skills[index++];
                const done = index === this.skills.length + 1;
                return {
                    value,
                    done
                };
            }
        }
    }
}

const mySkills = new Skill();
console.log([...mySkills]);
for (let skill of mySkills) {
    console.log(`My skill is ${skill}`);
}

Symbol.search

先来简单看个示例:

'angular'.search('ng') // 4

该示例的执行流程:

  1. 解析 'angular'.search('ng')
  2. 把 ‘angular’ 转换为字符串对象 new String('angular')
  3. 把 ‘ng’ 转换为正则对象 new Regexp('ng')
  4. 调用 ‘angular’ 字符串对象的 search 方法,该方法内部会自动调用 ng 正则对象的 Symbol.search 方法

具体可以参考以下伪代码:

// pseudo code for String class
class String {
    constructor(value) {
        this.value = value;
    }

    search(obj) {
        obj[Symbol.search](this.value);
    }
}

class RegExp {
    constructor(value) {
        this.value = value;
    }

    [Symbol.search](string) {
        return string.indexOf(this.value);
    }
}

此外利用 Symbol.search 我们还可以让 String.prototype.search() 方法调用我们自定义对象内部的 Symbol.search() 方法,从而实现自定义 search 逻辑:

class Article {
    constructor(tag) {
        this.tag = tag;
    }

    [Symbol.search](string) {
        return string.indexOf(this.tag) >= 0 ? 'Found' : 'Not_Found';
    }
}

var article = new Article('Angular');
console.log('Angular7'.search(article)); // Found
console.log('重温ES6'.search(article)); // Not_Found

以上示例的执行流程:

  1. 解析 'Angular7'.search(article) 语句
  2. 把 ‘Angular7’ 转换为字符串对象 new String("Angular7")
  3. 由于 article 是对象,这里不需要进行转换
  4. 调用 ‘Angular7’ 字符串对象的 search 方法,该方法会自动调用 article 对象内部的 Symbol.search 方法,比如 article[Symbol.search]('Angular7')

本文简单介绍了 ES6 Symbol 的一些特性,然后介绍了 Symbol 几个应用场景,若想进一步了解 Symbol,可以阅读一下冴羽大神写的ES6 系列之模拟实现 Symbol 类型这一篇文章。

参考资源

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 深入学习 Node.js Buffer

    ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 不能直接操作,而是要通过类型数组对象 或 DataView ...

    阿宝哥
  • 你不知道的 MutationObserver

    在某些场景下,我们希望能监视 DOM 树的变动,然后做一些相关的操作。比如监听元素被插入 DOM 或从 DOM 树中移除,然后添加相应的动画效果。或者在富文本编...

    阿宝哥
  • Angular 6.x 指令快速入门

    在 Angular 中,我们可以使用 HostBinding 装饰器,实现元素的属性绑定。

    阿宝哥
  • es6 Symbol

    1.Symbol 值通过Symbol 函数生成,凡是属性名属于Symbol 类型,就是   独一无二的,可以保证不会与其他属性名冲突。       // 没有参...

    用户1197315
  • 理解和使用ES6中的Symbol

    ES6中引入了一种新的基础数据类型:Symbol,不过很多开发者可能都不怎么了解它,或者觉得在实际的开发工作中并没有什么场景应用到它,那么今天我们来讲讲这个数据...

    一斤代码
  • ES6之symbol

    为什么需要使用Symbol 考虑到以下场景: // a library var L = (function() { var prop1 = 'prop1...

    糊糊糊糊糊了
  • ES6精华:Symbol

    https://segmentfault.com/a/1190000015244917

    前端博客 : alili.tech
  • ES6中的Symbol有什么卵用

    在ES6中新增了一中类型,这个类型叫做Symbol,最大的特点号称独一无二,下面我们来说一下这东西怎么用,最后再说一下他用在哪。

    无邪Z
  • Javascript Symbol 解惑 什么是Symbol创建Symbol如何使用Symbol

    Symbol是ES6中新引入的一种基本数据类型,在此之前Javascript中已有几种基本数据类型:

    MudOnTire
  • 前端测试题: 关于Symbol,错误的说法是?

    Symbol是由ES6规范引入的一项新特性,它的功能类似于一种标识唯一性的ID。通常情况下,我们可以通过调用Symbol()函数来创建一个Symbol实例.

    舒克

扫码关注云+社区

领取腾讯云代金券