摘要:是一个布尔值,用于确定当调用数组的方法时,如果传入参数是一个数组,是否需要将这个数组拍平。与其他的属性不同的是,并不默认出现在标准对象中。
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,至此ECMAScript的基本数据类型就有了6种:字符串,数字,布尔,null,undefined,Symbol。关于Symbol,我打算写2篇文章来提取一下比较重要的知识点,这篇是第一篇,主要讲Symbol的...
摘要:它是语言的第七种数据类型,前六种是布尔值字符串数值对象。在中,根据属性名来进行判断。,是一个布尔值,表示该对象使用时,是否可以展开。等同于,指向该对象的默认遍历器方法,即该对象进行循环时,会调用这个方法,返回该对象的默认遍历器。 本文字数:3000+,阅读时间6分钟。 如果有理解不到位的地方,欢迎大家纠错。如果觉得还可以,希望大家可以点个赞。 谢谢大家。 目录 一、Symbol是什么...
摘要:先搜索全局符号注册表,如果已有,则返回这个已存在的符号值否则,会创建一个新的符号值,并使用该键值将其记录到全局符号注册表中,然后返回这个新的符号值。 主要知识点:创建符号值、使用符号值、共享符号值、符号值转换。检索符号值属性以及知名符号 showImg(https://segmentfault.com/img/bVbfWhK?w=1203&h=633); 《深入理解ES6》笔记 目录 ...
摘要:的码点被称为基本字符区域。关于的介绍,我准备用文档阮一峰来做一些介绍,具体的可以参考文档引入的原因的对象属性名都是字符串,这容易造成属性名的冲突。其他的一些属性可以去看文档阮一峰注意函数前不能使用命令,否则会报错。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完...
阅读 3214·2021-09-22 16:06
阅读 3210·2021-09-02 15:40
阅读 607·2019-08-30 15:54
阅读 1013·2019-08-26 12:22
阅读 1347·2019-08-26 12:17
阅读 2726·2019-08-26 12:09
阅读 435·2019-08-26 10:20
阅读 759·2019-08-23 16:28