[JavaScript]Symbol类型-常用内置符号(二)

502 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 21 天,点击查看活动详情

常用内置符号

除了定义自己使用的Symbol值,ES6也提供了一批常用的内置符号,用于暴露语言内部行为。

ECMAScript 6 也引入了一批常用内置符号(well-known symbol),用于暴露语言内部行为,开发者 可以直接访问、重写或模拟这些行为。这些内置符号都以 Symbol 工厂函数字符串属性的形式存在。

内置符号最重要的用途之一是重新定义它们,从而改变原生结构的行为。

这些内置符号都是全局函数 Symbol 的普通字符串属性,指向一个符号的实例。其内置符号属性都是不可写、不可枚举、不可配置的。

1、Symbol.hasInstance

根据 ECMAScript 规范,这个符号作为一个属性表示“一个方法,该方法决定一个构造器对象是否认可一个对象是它的实例。由 instanceof 操作符使用”。

首先要知道 对象的Symbol.hasInstance属性, 指向的是一个方法;

其次,instanceof运算符知道吧,用过吧?我们知道可以使用 instanceof运算符 判断一个变量是否是某对象实例。

在 ES6 中,instanceof 操作符会使用 Symbol.hasInstance 函数来确定关系。


function Foo() {};
let f = new Foo();

console.log(f instanceof Foo); // true
console.log(Foo[Symbol.hasInstance](f)); // true

在继承的类上通过静态方法重新定义这个函数:

class EvenNum{
    static [Symbol.hasInstance](obj) {
        return Number(obj) % 2 === 0;
    }
}
1 instanceof EvenNum // false
2 instanceof EvenNum // true

2、Symbol.isConcatSpreadable

根据 ECMAScript 规范,这个符号作为一个属性表示“一个布尔值,如果是 true,则意味着对象应 该用 Array.prototype.concat()打平其数组元素”。

首先要知道 Symbol.isConcatSpreadable 表示一个布尔值;

其次,数组的concat()方法知道吧,用过吧?连接两个或多个数组。

let arr1= ['1','2'],
    arr2= ['3', '4', '5'];

let numarr = arr1.concat(arr2, '6')
console.log(numarr); // ['1', '2', '3', '4', '5', '6'];
arr1[Symbol.isConcatSpreadable] // undefined


arr1[Symbol.isConcatSpreadable]  = false;
numarr = arr1.concat(arr2, '6')
console.log(numarr); // [arr1, '3', '4', '5', '6']

arr1[Symbol.isConcatSpreadable]  = true;
arr2[Symbol.isConcatSpreadable]  = false;
numarr = arr1.concat(arr2, '6')
console.log(numarr); // ['1', '2', Array(3), '6']

concat()方法链接数组时,默认情况下会被打平到已有的数组;

Symbol.isConcatSpreadable默认等于undefined

如果把数组的Symbol.isConcatSpreadable设置成false; 那么连接多个数组时,这个值为false的数组会直接被追加到数组中,不会打平。

注意类数组与数组行为相反。类数组默认是追加到数组末尾,不会打平;可以为其设置为true就可以打平到数组中了。