JavaScript —— Symbol数据类型的拓展
上一篇文章学习了
Symbol
的基本用法和作用,但对于Symbol
的构造器对象,里面还有很多内置方法我们可以研究一下,让我们一起看看吧!
上一篇文章:《传送地址》
一、Symbol.hasInstance
hasInstance
?看起来好眼熟。难道它跟我们的某些API有关系?
没错!他就是instanceof
!当我们使用这个API判断类型的时候,就会调用这个类型构造器的内置对象属性。我们可以举个例子:
class myObject {
static [Symbol.hasInstance](obj) {
return obj.constructor === Object
}
}
console.log({} instanceof myObject) // true
// 相当于 myObject[Symbol.hasInstance]({})
console.log([] instanceof myObject) // false
// 相当于 myObject[Symbol.hasInstance]([])
上面这个例子,我们自己替myObject
这个类实现了对应instanceof
的内置方法,一般JavaScript的数据类型都内置有这个构造器对象属性,如果没有,则返回false
。
class myObject {
}
console.log({} instanceof myObject) // false
二、Symbol.iterator
当JavaScript的一些数据类型含有Symbol.iterator
内置对象属性时,我们把由这种数据类型创建的对象称为可迭代对象。
其作用是,当可迭代对象被for...of
语句调用时,返回默认的迭代器。在ES6
中,Array
、Set
、Map
和string
都是可迭代对象,他们都被内置了Symbol.iterator
对象属性。
什么意思呢?我们举个例子:
const arr = [1, 2, 3, 4, 5];
for (let a of arr) {
console.log(a);
}
// 输出 1
// 输出 2
// 输出 3
// 输出 4
// 输出 5
其实我们可以把它拆分出来,实际上在执行for...of
语句时,本质是下面这样的:
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // Object {value: 1, done: false}
console.log(iterator.next()); // Object {value: 2, done: false}
console.log(iterator.next()); // Object {value: 3, done: false}
console.log(iterator.next()); // Object {value: 4, done: false}
console.log(iterator.next()); // Object {value: 5, done: false}
console.log(iterator.next()); // Object {value: undefined, done: true}
执行for...of
循环的时候,先调用了arr
数组的Symbol.iterator
方法,由此来获取迭代器对象。接下来就是调用iterator.next()
方法将迭代器对象的value
属性赋值到a
当中,5次迭代之后,该对象的done
属性为true
,然后循环结束。
当然,我们也可以为自己的类定义集合且来实现可迭代对象:
class myArray {
constructor() {
this.myArr = [];
}
add(data) {
this.myArr.push(data);
return this;
}
*[Symbol.iterator]() {
for (let a of this.myArr) {
yield a;
}
}
}
// 1.创建对象
const otherArr = new myArray();
// 2.调用事先定义好的方法
otherArr.add(1);
otherArr.add(2);
otherArr.add(3);
otherArr.add(4);
otherArr.add(5);
// 3.使用for...of调用可迭代对象
for (let b of otherArr) {
console.log(b);
}
// 输出 1
// 输出 2
// 输出 3
// 输出 4
// 输出 5
反之,如果我们没有为类定义好内置的对象迭代属性,我们使用for...of
,就会报错:
class myArray {
constructor() {
this.myArr = [];
}
add(data) {
this.myArr.push(data);
return this;
}
}
// 1.创建对象
const otherArr = new myArray();
// 2.调用事先定义好的方法
otherArr.add(1);
otherArr.add(2);
otherArr.add(3);
otherArr.add(4);
otherArr.add(5);
// 3.使用for...of调用可迭代对象
for (let b of otherArr) {
console.log(b);
}
// 输出 Uncaught TypeError: otherArr is not iterable,即 otherArr 不是可迭代对象
三、总结
其实也没有什么好总结的,只是,我们要知道是这个数据类型Symbol
它的一些能力即可。上面两点只是我临时起意,就码来玩玩,大家有兴趣的可以继续研究最上面的那个截图~