1. Symbol.for(),Symbol.keyFor()
有时候我们希望能够重用一个Symbol
值,这时候我们可以使用Symbol.for()
,该方法能够接受一个参数,然后会在一个“登记表”中搜索使用该参数作为描述的Symbol
值是否存在,如果存在,则返回已经存在的Symbol值
,如果不存在就用该参数作为描述生成一个新的Symbol
值。该方法和Symbol()
方法的区别是,该方法会将生成的Symbol
登记在全局环境中,而Symbol()
不会。
let s1 = Symbol('a')
let s2 = Symbol.for('a')
let s3 = Symbol.for('a')
s1 === s2 // false
s2 === s3 // true
通过上面的代码我们可以发现,尽管s1
是以字符a
作为描述的s2
是通过在全局登记中搜索以字符a
作为描述的Symbol
值,但是s1
和s2
不相等说明搜索失败,s2
是重新生成的Symbol
值,即Symbol()
生成的值并没有登记,s2
和s3
相等,说明s3
是搜索到已经存在的Symbol
值。
使用Symbol.keyFor()
可以返回一个已经登记的Symbol
值的描述,即key
值
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"
let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined
因为s2
未登记,所以该方法无法查询到其key
值
2. 内置的Symbol方法
2.1 Symbol.hasInstance
对象的Symbol.hasInstance
属性其实指向的是一个内部的方法,当其他对象使用instanceof
运算符时会自动调用该方法:
class MyClass {
[Symbol.hasInstance](foo) {
return foo instanceof Array;
}
}
[1, 2, 3] instanceof new MyClass() // true
2.2 Symbol.isConcatSpreadable
对象的Symbol.isConcatSpreadable
属性等于一个布尔值,表示该对象用于Array.prototype.concat()
时,是否可以展开。
let arr1 = ['c', 'd'];
['a', 'b'].concat(arr1, 'e') // ['a', 'b', 'c', 'd', 'e']
arr1[Symbol.isConcatSpreadable] // undefined
let arr2 = ['c', 'd'];
arr2[Symbol.isConcatSpreadable] = false;
['a', 'b'].concat(arr2, 'e') // ['a', 'b', ['c','d'], 'e']
let arr3 = ['c', 'd'];
arr2[Symbol.isConcatSpreadable] = true;
['a', 'b'].concat(arr2, 'e') // ['a', 'b', ['c','d'], 'e']
通过上面的代码我们可以发现,Arry
默认是可以展开的,并且Symbol.isConcatSpreadable
的默认值为undefined
,当该属性值为true
时数组也可以展开,只有当该属性值为false
的时候表示调用concat
的时候数组不能被展开。
2.3 Symbol.match
对象的Symbol.match
属性,指向一个函数。当执行str.match(myObject)
时,如果该属性存在,会调用它,返回该方法的返回值。
String.prototype.match(regexp)
// 等同于
regexp[Symbol.match](this)
class MyMatcher {
[Symbol.match](string) {
return 'hello world'.indexOf(string);
}
}
'e'.match(new MyMatcher()) // 1
2.4 Symbol.replace
对象的Symbol.replace
属性,指向一个方法,当该对象被String.prototype.replace
方法调用时,会返回该方法的返回值。
String.prototype.replace(searchValue, replaceValue)
// 等同于
searchValue[Symbol.replace](this, replaceValue)
下面是一个例子。
const x = {};
x[Symbol.replace] = (...s) => console.log(s);
'Hello'.replace(x, 'World') // ["Hello", "World"]
Symbol.replace
方法会收到两个参数,第一个参数是replace
方法正在作用的对象,上面例子是Hello
,第二个参数是替换后的值,上面例子是World
。
网友评论