Lazy evaluation
常被译为“延迟计算”或“惰性计算”,指的是仅仅在真正需要执行的时候才计算表达式的值。
与惰性求值
相反的是及早求值(eager evaluation)
及早求值,也被称为贪婪求值
(greedy evaluation)或严格求值,是多数传统编程语言的求值策略。
充分利用惰性求值
的特性带来的好处主要体现在以下两个方面:
-
避免不必要的计算,带来性能上的提升。
-
节省空间,使得无限循环的数据结构成为可能。
ES6 中的迭代器使惰性求值和创建用户定义的数据序列成为可能。迭代是一种遍历数据的机制。 迭代器是用于遍历数据结构元素(称为Iterable
)的指针,用于产生值序列的指针。
迭代器是一个可以被迭代的对象。它抽象了数据容器,使其行为类似于可迭代对象。
迭代器在实例化时不计算每个项目的值,仅在请求时才生成下一个值。 这非常有用,特别是对于大型数据集或无限个元素的序列。
可迭代对象是希望其元素可被公众访问的数据结构。JS 中的很多对象都是可迭代的,它们可能不是很好的察觉,但是如果仔细检查,就会发现迭代的特征:
-
new Map([iterable])
-
new WeakMap([iterable])
-
new Set([iterable])
-
new WeakSet([iterable])
-
Promise.all([iterable])
-
Promise.race([iterable])
-
Array.from([iterable])
还有需要一个可迭代的对象,否则,它将抛出一个类型错误,例如:
-
for ... of
-
...
(展开操作符)
const [a, b, ..] = iterable
(解构赋值)
yield*
(生成器)
JavaScript中已有许多内置的可迭代项:
String
,Array
,TypedArray
,Map
,Set
。
迭代器和可迭对象遵循迭代协议
。
协议是一组接口,并规定了如何使用它们。
迭代器遵循迭代器协议,可迭代遵循可迭代协议。
可迭代的协议
要使对象变得可迭代,它必须实现一个通过Symbol.iterator
的迭代器方法,这个方法是迭代器的工厂。
使用 TypeScript,可迭代协议如下所示:
interface Iterable {
Symbol.iterator : Iterator;
}
Symbol.iterator]()
是无参数函数。 在可迭代对象上调用它,这意味着我们可以通过this
来访问可迭代对象,它可以是常规函数或生成器函数。
迭代器协议
迭代器协议定义了产生值序列的标准方法。
为了使对象成为迭代器,它必须实现next()
方法。 迭代器可以实现return()
方法,我们将在本文后面讨论这个问题。
使用 TypeScript,迭代器协议如下所示:
interface Iterator {
next() : IteratorResult;
return?(value?: any): IteratorResult;
}
IteratorResult
的定义如下:
interface IteratorResult {
value?: any;
done: boolean;
}
-
done
通知消费者迭代器是否已经被使用,false
表示仍有值需要生成,true
表示迭代器已经结束。 -
value
可以是任何 JS 值,它是向消费者展示的值。
当done
为true
时,可以省略value
。
迭代器和可以可迭代对象可以用下面这张图来表示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qu7BEdCY-1606263454066)(/img/bVbOVew)]
基础知识介绍完了,接着,我们来配合一些事例来加深我们的映像。
范围迭代器
我们先从一个非常基本的迭代器开始,createRangeIterator
迭代器。
我们手动调用it.next()
以获得下一个IteratorResult
。 最后一次调用返回{done:true}
,这意味着迭代器现在已被使用,不再产生任何值。
function createRangeIterator(from, to) {
let i = from;
return {
next() {
if (i <= to) {
return { value: i++, done: false };
} else {
return { done: true };
}
}
}
}
const it = createRangeIterator(1, 3);
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-auJn06E3-1606263454068)(/img/bVbOViQ)]
可迭代范围迭代器
在本文的前面,我已经提到 JS 中的某些语句需要一个可迭代的对象。 因此,我们前面的示例在与for ... of
循环一起使用时将不起作用。
但是创建符合迭代器
和可迭代协议
的对象非常容易。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SUzWxihn-1606263454070)(/img/bVbOVxd)]
function createRangeIterator (from, to) {
let i = from
return {
[Symbol.iterator] () {
return this
},
next() {
if (i <= to) {
return { value: i++, done: false }
} else {
return { done: true }
}
}
}
}
const it = createRangeIterator(1, 3)
for (const i of it) {
console.log(i)
}
迭代器可以表示无限制大小的序列,因为它们仅在需要时才计算值。
注意不要在无限迭代器上使用扩展运算符(...
),JS 将尝试消费迭代器,由于迭代器是无限的,因此它将永远不会结束。 所以你的应用程序将崩溃,因为内存已被耗尽 😱
同样,for ... of
循环也是一样的情况,所以要确保能退出循环:
function createEvenNumbersIterator () {
let value = 0
return {
[Symbol.iterator] () {
return this
},
next () {
value += 2
return { value, done: false}
}
}
}
const it = createEvenNumbersIterator()
const [a, b, c] = it
console.log({a, b, c})
const [x, y, z] = it
console.log({ x, y, z })
for (const even of it) {
console.log(even)
if (even > 20) {
break
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
最后
最后写上我自己一直喜欢的一句名言:
世界上只有一种真正的英雄主义就是在认清生活真相之后仍然热爱它
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
899679)]
最后
最后写上我自己一直喜欢的一句名言:
世界上只有一种真正的英雄主义就是在认清生活真相之后仍然热爱它
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-nYpxhoab-1712674899680)]