一、内置方法
- asyncIterator:异步迭代器
- iterator:迭代器
- for
- keyFor
- hasInstance
- isConcatSpreadable
- match
- matchAll
- replace
- split
- search
- species
- toPrimitive
- toStringTag
- unscopables
- useSetter
- useSimple
二、部分API解析
1、异步迭代器(asyncIterator)
- 定义:指定了一个对象的默认的异步迭代器,如果一个对象设置了这个属性,那么它就是异步可迭代对象,可用于for await…of 循环。
- 给一个对象添加asyncIterator属性:
let as_iterator = new Object();
as_iterator[Symbol.asyncIterator] = async function* () {
yield 'hello';
yield 'waiting';
yield 'ending';
}
(async()=>{
for await(let a of as_iterator) {
console.log(a);
// hello
// waiting
// ending
}
})();
【注:】暂时没有设置了[Symbol.asyncIterator]这个属性的JavaScript对象
2、迭代器(iterator)
-
定义:
为每一个对象定义了默认的迭代器,该迭代器可被【for…of】循环使用 -
拥有迭代器属性的对象:
- String
- Map
- Set
- Array
- arguments
- … …
-
自定义迭代器:
1.利用generator函数:
let my_iterator = {
[Symbol.iterator] : function* () {
yield 'hello';
yield 'waiting';
yield 'ending';
}
}
console.log([...my_iterator]); // ['hello', 'waiting', 'ending']
2.数据结构默认的Iterator接口,可以通过for…of使用。解构赋值用的也是Iterator接口。
const other_iterator = {
data: ['hello', 'welcome', 'world'],
[Symbol.iterator]() {
const self = this;
let ind = 0;
return {
next() {
if (ind < self.data.length) {
return {
value: self.data[ind++],
one: false
}
} else {
return {
value: undefined,
done: true
}
}
}
}
},
a: 1,
b: 2
}
let abs = other_iterator[Symbol.iterator]()
console.log(abs.next()); // {value: 'hello', one: false}
console.log(abs.next()); // {value: 'welcome', one: false}
console.log(abs.next()); // {value: 'world', one: false}
console.log(abs.next()); // {value: undefined, done: true}
3、for
- 定义:不同的变量可以使用同一个Symbol值,Symbol.for()方法接收一个参数,然后查找是否有以该参数作为名称的Symbol值,如果有就返回这个Symbol值,否则就新建一个以该参数为名称的Symbol值。
let a = Symbol('symbol')
let b = Symbol('symbol')
console.log(a === b); // false
let symbol_a = Symbol.for('symbol');
let symbol_b = Symbol.for('symbol');
console.log(symbol_a === symbol_b); // true
4、keyFor
- 定义: 返回一个已使用的 Symbol 类型值的key,用来检测该参数作为名称的 Symbol 值是否已被使用
/** Symbol.keyFor */
let a = Symbol.for('symbol');
let b = Symbol.keyFor(a)
console.log(b); // symbol
console.log(a); // Symbol(symbol)
console.log(a === b); // false
5、hasInstance
- 定义: 当我们使用instanceof这个方法去检测对象A是不是B 的实例的时候,实际上B就是调用的 B[Symbol.hasInstance] 这个方法。
1、常规使用
class Event {}
let e = new Event;
console.log(e instanceof Event); // true
console.log(Event[Symbol.hasInstance](e)); // true
2、更改 [Symbol.hasInstance] 指向
class my_instance {
static [Symbol.hasInstance](params) {
typeof params
}
}
let a = new my_instance();
console.log(a instanceof my_instance); // false
console.log(my_instance[Symbol.hasInstance](a)); // undefined
6、isConcatSpreadable
- 定义: 当我们使用 Array.prototype.concat 这个方法时,可以利用这个属性去控制是否展开合并的数组。
/* isConcatSpreadable */
const arr1 = [1, 2, 3, 4]
const arr2 = ['a', 'c', 'b', 8]
let arr = arr1.concat(arr2)
console.log(arr); // [1, 2, 3, 4, 'a', 'c', 'b', 8]
arr2[Symbol.isConcatSpreadable] = false;
// arr1[Symbol.isConcatSpreadable] = false;
let arg = arr1.concat(arr2)
console.log(arg); // [1, 2, 3, 4, Array(4)]
7、match
- 定义: 指定了匹配的是正则表达式,而不是字符串。String.prototype.match 会调用此方法。
/* match */
let regexp = /testssymbolmatch/;
regexp[Symbol.match] = false
console.log('/test/'.startsWith(regexp)); // false
console.log('/test/'.endsWith(regexp)); // false
console.log('/testssymbolmatch/'.startsWith(regexp)); // true
console.log('/testssymbolmatch/'.endsWith(regexp)); // true
当不设置 [Symbol.match] 这个属性为 false的时候:
console.log('/testssymbolmatch/'.startsWith(/testssymbolmatch/));
Uncaught TypeError: First argument to String.prototype.startsWith must not be a regular expression
8、matcAll
- 定义: 返回一个迭代器,该迭代器根据字符串生成正则表达式的匹配项。可以被 [String.prototype.matchAll] 调用
/* matchAll */
const exp = /\d+/g
const str ='2022-05-11 17:13:14';
let res = exp[Symbol.matchAll](str)
console.log(res); // RegExpStringIterator {}
console.log(...res)
/**
* ['2022', index: 0, input: '2022-05-11 17:13:14', groups: undefined]
* ['05', index: 5, input: '2022-05-11 17:13:14', groups: undefined]
* ['11', index: 8, input: '2022-05-11 17:13:14', groups: undefined]
* ['17', index: 11, input: '2022-05-11 17:13:14', groups: undefined]
* ['13', index: 14, input: '2022-05-11 17:13:14', groups: undefined]
* ['14', index: 17, input: '2022-05-11 17:13:14', groups: undefined]
*/
9、replace
- 定义: 指定了当一个字符串替换所匹配字符串时调用的方法。【String.prototype.replace () 】会调用此方法。
该方法是正则(RegExp)原型上的一个方法,用来解析【String.prototype.replace () 】执行的时候传递进来的正则表达式,并对正则表达式匹配后的结果进行求值
let publicStr = 'anfdsvka fahF KJ'
RegExp.prototype[Symbol.replace] = () =>{
return 'qqq'
}
let s = publicStr.replace(/\a/g,'2')
console.log(s); // 'qqq'
10、split
- 定义: 指向一个正则表达式的索引处分隔字符串的方法。此方法通过【 String.prototype.split() 】调用。
其也是正则原型上的一个方法,在字符串使用split方法的时候会调用改方法。
RegExp.prototype[Symbol.split] = () => {
return [1, 2, 3];
}
s = publicStr.split(/\n/)
console.log(s); // [1, 2, 3]
11、search
- 定义: 指定了一个搜索方法,该方法接受一个正则表达式,该方法返回的是字符串中匹配到正则表达式的索引。此方法通过【String.prototype.search()】来调用。
1、正常使用:
let publicStr = 'anfdsvka fahF KJ'
let s= publicStr.search(/\a/g)
console.log(s); // 0
2、更改正则原型上的此方法
RegExp.prototype[Symbol.search] = () => {
return -1;
}
console.log(s); // -1
12、species
- 定义: 是个函数值属性,其被构造函数用以创建派生对象。
该属性在内置类型中最常用,用于对内置类型实例方法的返回值暴露实例化派生对象的方法。
基本使用:
class A extends Array { }
let a = new A;
console.log(a instanceof A); // true
console.log(a instanceof Array); // true
a.concat('123');
console.log(a instanceof A); // true
console.log(a instanceof Array); // true
用 Symbol.species 定义静态的获取器(getter),可以覆盖新创建实例的原型定义:
class B extends Array {
static get [Symbol.species]() {
return Array;
}
}
let b = new B;
console.log(b instanceof B); // true
console.log(b instanceof Array); // true
b = b.concat('3121');
console.log(b instanceof B); // fales
console.log(b instanceof Array); // true
13、 toPrimitive
- 定义: 是一个内置的 Symbol 值,它是作为对象的函数值属性存在的,当一个对象转换为对应的原始值时,会调用此函数。
const p1 = {
[Symbol.toPrimitive](state) {
switch (state) {
case 'number':
return 123;
case 'string':
return 'abc';
default:
return NaN;
}
}
}
console.log(p1); // { [Symbol(Symbol.toPrimitive)]: [Function: [Symbol.toPrimitive]] }
console.log(+p1); // 123
console.log(Number(p1)); // 123
console.log(String(p1)); // 'abc'
14、toStringTag
- 定义: 是一个内置 symbol,它通常作为对象的属性键使用,对应的属性值应该为字符串类型,这个字符串用来表示该对象的自定义类型标签,通常只有内置的 Object.prototype.toString() 方法会去读取这个标签并把它包含在自己的返回值里。
class Fn {
[Symbol.toStringTag]= 'Fn';
}
Fn.prototype[Symbol.toStringTag] = 'Fn';
let f = new Fn;
console.log({}.toString.call(f)); // '[object Fn]'
15、unscopables
- 定义: 指用于指定对象值,其对象自身和继承的从关联对象的 with 环境绑定中排除的属性名称。
const publicObj = {
a: '123',
b: '234',
c: undefined
}
publicObj[Symbol.unscopables] = {
a: true,
b: false
}
with(publicObj) {
console.log(a); // Uncaught ReferenceError: a is not defined
console.log(b); // '234'
console.log(c); // undefined
}
三、总结
- asyncIterator 暂时无设置有该属性的JS对象;
- iterator 迭代器,是在开发中可能会经常涉及到的一个Symbol属性,拥有该属性的数据类型包含:String、Array、arguments、Set、Map等;
- hasInstance 在使用instanceof方法检测数据类型的时候,会优先调用此方法;
- 正则对象的原型上的方法包含:match、matcAll、replace、split、search
- toStringTag 在使用 Object.prototype.toString() 去检测数据类型的时候,会优先调用 Symbol.toStringTag 这个方法