资讯专栏INFORMATION COLUMN

ES6 Symbol - 一些重要的Symbol属性

Barrior / 500人阅读

摘要:是一个布尔值,用于确定当调用数组的方法时,如果传入参数是一个数组,是否需要将这个数组拍平。与其他的属性不同的是,并不默认出现在标准对象中。

ECMAScript 6 通过在原型链上定义与Symbol相关的属性来暴露语言内部逻辑,使得开发者可以对一些语言的默认行为做配置。接下来我们来看看有哪些重要的Symbol属性可供我们使用:

1: Symbol.hasInstance 一个在执行 instanceof 时调用的方法,用于检测对象的继承信息
2: Symbol.isConcatSpreadable 一个布尔值,用于表示当传递一个集合作为Array.prototype.concat()的参数是,是否应该将集合内的元素拍平到同一层级
3: Symbol.iterator 在迭代器和生成器那篇文章已经细讲过

4: Symbol.match 一个在调用String.prototype.match()时调用的方法,用于比较字符串
5: Symbol.replace 一个在调用String.prototype.replace()时调用的方法,用于替换字符串的子串
6: Symbol.search 一个在调用String.prototype.search()时调用的方法,用于定位子串在字符串中的位置
7: Symbol.split 一个在调用String.prototype.split()时调用的方法,用于分割字符串

8: Symbol.species 用于创建派生对象的构造函数
9: Symbol.toPrimitive 一个返回对象原始值的方法
10: Symbol.toStringTag 一个在调用Object.prototype.toString()时使用的字符换,用于创建对象的描述
11: Symbol.unscopables 一个定义了一些不可被with语句引用的对象属性名称的对象集合

上面的属性很多,这里会挑一些比较重要和常用的来讲:
1: Symbol.hasInstance
Symbol.hasInstance用于确定对象是否为函数的实例。此方法定义在Function.prototype中,所以所有的函数都默认继承了此方法。当我们在调用例如

 obj instanceof Array;

其实等价于:

Array[Symbol.instanceof](obj);

文章开头我们就说了这些symbol属性是为了开发者能定制化语言的内部逻辑,那我们怎样改写Symbol.hasInstance的默认行为呢?这里面有一点特殊的是,为了确保Symbol.instance不会被意外地重写,该方法是被默认定义为不可写,不可配置,和不可枚举。如果确定要改写它,必须通过Object.definePropoty()方法:

function MyObject(){};
Object.defineProperty(MyObject, Symbol.hasInstance, {
    value: function () {
        return false;
    }
});
let obj = new MyObject();
console.log(obj instanceof MyObject); // false

以上代码,我们就重写了Symbol.hasInstance的默认逻辑,让它始终返回false,所以哪怕明明 obj instanceof MyObject 逻辑上应该返回true,但是结果得到false。 这个例子本身逻辑上没有意义,甚至是错误地,只是想要展示一下Symbol.hasInstance的用法。

我们还也可以让Symbol.hasInstance只是某些情况下返回true,但是一定要保证instanceof的左边是一个对象,这样才能触发对Symbol.hasInstance的调用,不然instanceof总是返回false。

2: Symbol.isConcatSpreadable
Symbol.isConcatSpreadable是一个布尔值,用于确定当调用数组的concat()方法时,如果传入参数是一个数组,是否需要将这个数组拍平。看下面一段代码:

Array.prototype[Symbol.isConcatSpreadable] = false;
let result = [1, 2].concat([3, 4], 5);
console.log(result);//[[1, 2], [3, 4], 5]

对比一下Symbol.isConcatSpreadable为true的情况:

Array.prototype[Symbol.isConcatSpreadable] = true;
let result = [1, 2].concat([3, 4], 5);
console.log(result); // [1, 2, 3, 4, 5]

ES6之前,对于concat()参数为数组的情况,默认是拍平为一个层级的。ES6提供了这个窗口,让开发者觉得这一行为。但是这里不建议直接修改Array的Symbol.isConcatSpreadable属性,如果真的需要修改这一属性,可以在派生数组子类里面进行修改。

与其他的Symbol属性不同的是,Symbol.isConcatSpreadable并不默认出现在标准对象中。在一个类数组对象中,如果我们设置Symbol.isConcatSpreadable属性为true,当执行concat()时,类数组对象的数值型属性也会被独立添加到concat()的调用结果中:

let collection = {
    0: "a",
    1: "b",
    length: 2,
    [Symbol.isConcatSpreadable]: true
};
console.log(["test"].concat(collection)); // ["test", "a", "b"]

3: Symbol.match, Symbol.replace, Symbol.search, Symbol.split
通常我们对一个字符串调用match(), replace(), search(), split()方法,它们的参数,既可以是字符串,也可以是一个正则表达式。但是它们本身内部的逻辑,我们是不能修改的。而Symbol.match, Symbol.replace, Symbol.search, Symbol.split这四个属性,就是开放了这个窗口,让开发者可以自行定义其内部逻辑,下面开一个Symbol.match的例子,其他三个也是一样的:

let hasLengthOf10 = {
    [Symbol.match]: function (value) {
        return value.length === 10 ? [value] : null
    }
};
console.log("abcdefghij".match(hasLengthOf10)); // [abcdefghij]
console.log("abcdefghi".match(hasLengthOf10)); // null

4: Symbol.toPrimitive
我们知道,对象不属于基本类型。那如果我们对对象进行一些基本类型的操作会怎样呢?比如alert一个对象:alert(obj), 或者对对象进行数学计算:obj1 - obj2, obj3 / 4等。一般呢,这些情况下,需要将对象先转换为基本数据类型,但是转换的规则是什么呢?ES6提供了Symbol.toPrimitive方法给开发者,开发者可以自行定义。Symbol.toPrimitive有一个重要的参数,规范中叫做类型提示(hint)。hint为String类型,有三种可能的值:

1: "number" 当转换场景为需要对象作为一个数字
2: "string" 当转换场景为需要对象作为一个字符串
3: "default" 当转换场景模棱两可的时候

这里需要注意的是,hint是JavaScript的引擎传入给Symbol.toPrimitive方法,开发者只需要针对它可能的三种值编写自己的逻辑,例如:

let person = {
    "name": "mike",
    "age": 24,
    [Symbol.toPrimitive](hint) {
        switch (hint) {
            case "number": {
                return this.age;

            }
            case "string": {
                return this.name
            }

            case "default": {
                return this.age + this.name
            }
        }

    }
};

console.log(person / 2); // 12
alert(person);// alert弹窗内容为 mike
console.log(person + 100); // 24mike100

代码console.log(person + 100)这里执行了一个加法操作,因为加法既可以用作字符串类型,也可以用作数字类型,所以这里就命中了hint为"default"的情况。

5: Symbol.toStringTag
Symbol.toStringTag定义了调用Object.prototype.toString()是返回的身份标识。例如调用:

Object.prototype.toString.call([]);// "[object Array]"

"Array"这是储存在数组对象的Symbol.toStringTag属性中。
一般我们自己创建的对象,如果调用以上方法,或者对象的toString()方法会得到"[object Object]"。我们可以重写对象的Symbol.toStringTag来自定义对象调用toString()方法时得到的值:

function Person(name) {
    this.name = name;

}
Person.prototype[Symbol.toStringTag] = "Person";
let mike = new Person("mike");

console.log(Object.prototype.toString.call(mike)); // [object Person]
console.log(mike.toString());// [object Person]

但是,你也可以重写对象的toString()方法,这样并不会对Object.prototype.toString.call()造成影响:

function Person(name) {
    this.name = name;

}
let mike = new Person("mike");
Person.prototype[Symbol.toStringTag] = "Person";
Person.prototype.toString = function () {
    return this.name;
};
console.log(Object.prototype.toString.call(mike));// [object Person]
console.log(mike.toString());// mike

以上就是所有的几个比较重要的Symbol属性。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106014.html

相关文章

  • ES6 Symbol - 基本使用方法

    摘要:但是,前来提到的个方法都不支持属性,为了保持原有的功能,新增了一个方法来检索类型的属性接下来看一下式例以上,就是关于的基本使用方法。 ES6新增了一个基本数据类型:Symbol,至此ECMAScript的基本数据类型就有了6种:字符串,数字,布尔,null,undefined,Symbol。关于Symbol,我打算写2篇文章来提取一下比较重要的知识点,这篇是第一篇,主要讲Symbol的...

    paney129 评论0 收藏0
  • ES6脚丫系列】Symbol

    摘要:它是语言的第七种数据类型,前六种是布尔值字符串数值对象。在中,根据属性名来进行判断。,是一个布尔值,表示该对象使用时,是否可以展开。等同于,指向该对象的默认遍历器方法,即该对象进行循环时,会调用这个方法,返回该对象的默认遍历器。 本文字数:3000+,阅读时间6分钟。 如果有理解不到位的地方,欢迎大家纠错。如果觉得还可以,希望大家可以点个赞。 谢谢大家。 目录 一、Symbol是什么...

    Flands 评论0 收藏0
  • 深入理解ES6笔记(六)SymbolSymbol属性

    摘要:先搜索全局符号注册表,如果已有,则返回这个已存在的符号值否则,会创建一个新的符号值,并使用该键值将其记录到全局符号注册表中,然后返回这个新的符号值。 主要知识点:创建符号值、使用符号值、共享符号值、符号值转换。检索符号值属性以及知名符号 showImg(https://segmentfault.com/img/bVbfWhK?w=1203&h=633); 《深入理解ES6》笔记 目录 ...

    crossea 评论0 收藏0
  • symbol

    摘要:元编程另一个方面是反射其用于发现和调整你的应用程序结构和语义。下的元编程带来了三个全新的以及。它是语言的第七种数据类型,前六种是布尔值字符串数值对象。等同于对象的属性等于一个布尔值,表示该对象用于时,是否可以展开。 元编程 一系列优秀的 ES6 的新特性都来自于新的元编程工具,这些工具将底层钩子(hooks)注入到了代码机制中。元编程(笼统地说)是所有关于一门语言的底层机制,而不是数据...

    jubincn 评论0 收藏0
  • 重学前端学习笔记(六)--JavaScript类型有哪些你不知道细节?

    摘要:的码点被称为基本字符区域。关于的介绍,我准备用文档阮一峰来做一些介绍,具体的可以参考文档引入的原因的对象属性名都是字符串,这容易造成属性名的冲突。其他的一些属性可以去看文档阮一峰注意函数前不能使用命令,否则会报错。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完...

    Lsnsh 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<