js 迭代器
ヤッハロー、Kaiqisanすうう、一つふつうの学生プログラマである ,这里,终于。。终于要讲迭代的原理----迭代器了,这篇文章可能讲得不是很好,大家直接看代码就可以了。
Iterator
,一个迭代器对象,能拥有迭代机制。它拥有方法next(),可迭代下一个成员,也拥有属性Symbol.toStringTag,在创建对象的默认字符串描述中使用的字符串值属性,它由该Object.prototype.toString()
方法在内部访问。
一般使用迭代器的方法有 forEach() every() some() reduce() map() filter()
下面为打开迭代器的方法
let arr = [2, 2, 4, 8]
console.log(arr.entries())
console.log(arr.keys())
console.log(arr.values())
这三个方法都可以打开迭代器,下面以entries()方法为例。
let arr = [2, 4, 8, 16]
let a = arr.entries() // 获取迭代器iterator
console.log(a.next()); // 第一次迭代,返回 { value: [0: 2], done: false }
console.log(a.next()); // 第二次迭代,返回 { value: [1: 4], done: false }
console.log(a.next()); // 第三次迭代,返回 { value: [2: 8], done: false }
console.log(a.next()); // 第四次迭代,返回 { value: [3: 16], done: false }
console.log(a.next());
// 第五次迭代,此时迭代已经完成,不会再返回值,返回 { value: undefined, done: true }
迭代器迭代数组的时候,每一次迭代都获取其相应要获取的值,并实时反馈当前是否已经结束迭代。
下面为iterator的方法模拟。
function iterator(arr){
let i = 0;
return {
next: function(){
return i < arr.length ?
{ value: arr[i++], done: false }:
{ value: undefined, done: true }
}
}
}
这个迭代器设计一方面是为了实现for of 自动迭代,只要一个参数它部署了Symbol.iterator属性,就可以通过for of实现自动迭代。
let arr = [2, 4, 8, 16]
for (let [item, i] of arr.entries()) {
console.log(item, i)
}
// 输出结果
// 0 2
// 1 4
// 2 8
// 3 16
let arr = [2, 4, 8, 16]
for (let item of arr.values()) {
console.log(item)
}
// 2
// 4
// 8
// 16
之前也还提到for of 无法遍历对象,就是因为对象内部没有自带的迭代器。为了实现对象的for of迭代,我们选择为它添加一个迭代器,这也是一个迭代器的工作原理。
let obj = {
name: 'kaiqisan',
uid: 10001,
sex: '男'
}
obj[Symbol.iterator] = function () {
let keys = Object.keys(this) // 指向引用这个方法的对象obj
let count = 0
return {
next() {
if (count < keys.length) {
return { value: obj[keys[count++]], done: false }
} else {
return { value: undefined, done: true }
}
}
}
}
for (let item of obj) {
console.log(item)
}
// kaiqisan
// 10001
// 男
但其实,说实在的,数组在本质上面其实就是对象,如果不信,请输入以下代码查看一下
console.log(typeof []); // object
数组这个“对象”,已经自动对成员分配键名,那就是它的下标,它还有length长度属性,当然,我们也可以自己添加属性值,也可以为其原型添加方法.
Array.prototype.getName = function() {
console.log('ok')
}
又因为数组方便遍历,也又经常被遍历,所以它的原型拥有迭代器。
console.log([].__proto__); // 打开看看
总结
有时候,我们多逛逛底层,研究底层的原理,这样,我们才能对js有更加深刻的理解,其实不止js,学别的语言也应如此。就像是面试java岗的人经常被问到是否研究过spring的源码,面试官就是考察您的钻研能力与学习能力。嘛,为了找到工作,也为了提升自己,请务必多多研究底层原理,语言是一种工具,拆开查看内部构造能为日后更加得心应手打造一个良好的基础。