永久免费网站建立,公司官网设计模板,精准的搜索引擎优化,玉林网站推广小时候#xff0c; 乡愁是一枚小小的邮票#xff0c; 我在这头#xff0c; 母亲在那头。 长大后#xff0c;乡愁是一张窄窄的船票#xff0c; 我在这头#xff0c; 新娘在那头。 后来啊#xff0c; 乡愁是一方矮矮的坟墓#xff0c; 我在外头#xff0c; 母亲在里头。… 小时候 乡愁是一枚小小的邮票 我在这头 母亲在那头。 长大后乡愁是一张窄窄的船票 我在这头 新娘在那头。 后来啊 乡愁是一方矮矮的坟墓 我在外头 母亲在里头。 而现在 乡愁是一湾浅浅的海峡 我在这头 大陆在那头。 ——余光中《乡愁》 本文为读 lodash 源码的第三篇后续文章会更新到这个仓库中欢迎 starpocket-lodash gitbook也会同步仓库的更新gitbook地址pocket-lodash 作用与用法 compact 函数用来去除数组中的假值并返回由不为假值元素组成的新数组。 false、null、0、 、undefined 和 NaN 都为假值。 例如 var arr [1,false,2,null,3,0,4,NaN,5,undefined]
_.compact(arr) // 返回 [12345] 源码 function compact(array) {let resIndex 0const result []if (array null) {return result}for (const value of array) {if (value) {result[resIndex] value}}return result
} compact 的源码只有寥寥几行相当简单。 首先判断传入的数组是否为 null 或者 undefined如果是则返回空数组。 然后用 for...of 来取得数组中每项的值如果不为假值则存入新数组 result 中最后将新数组返回。 到这里源码分析完了。 但是在看源码的时候发现这里用了 for...of 来做遍历其实除了 for...of 外也可以用 for 或者 for...in 来做遍历那为什么最后选了 for...of 呢 数组中的for循环 使用 for 循环很容易就将 compact 中关于循环部分的源码改写成以下形式 for (let i 0; i array.length; i) {const value array[i]if (value) {result[resIndex] value}} 这样写肯定是没有问题的但是不够简洁。 for…in 再来看 for...in 循环先来将源码改写一下 for (let index in array) {const value array[i]if (value) {result[resIndex] value}
} 先看看MDN上关于 for...in 的用法 for...in语句以任意顺序遍历一个对象的可枚举属性。 关于可枚举属性可以点击上面的链接到MDN上了解一下这里不做太多的解释。 在数组中数组的索引是可枚举属性可以用 for...in 来遍历数组的索引数组中的稀疏部分不存在索引可以避免用 for 循环造成无效遍历的弊端。 但是for...in 有两个致命的特性 for...in 的遍历不能保证顺序for...in 会遍历所有可枚举属性包括继承的属性。for...in 的遍历顺序依赖于执行环境不同执行环境的实现方式可能会不一样。单凭这一点就断然不能在数组遍历中使用 for...in大多数情况下顺序对于数组的遍历都相当重要。 关于第二点先看个例子 var arr [1,2,3]
arr.foo foo
for (let index in arr) {console.log(index)
} 在这个例子中你期望输出的是 0,1,2但是最后输出的可能是 0,1,2,foo for...in 不能保证顺序。因为 foo 也是可枚举属性在 for..in 会被遍历出来。 for…of 最后来看看 for...of。 当我们在控制台中打印一个数组并将它展开来查看时会在数组的原型链上发现一个很特别的属性 Symbol.iterator。 其实 for...of 循环内部调用的就是数组原型链上的 Symbol.iterator 方法。 Symbol.iterator 在调用的时候会返回一个遍历器对象这个遍历器对象中包含 next 方法for...of 在每次循环的时候都会调用 next 方法来获取值直到 next 返回的对象中的 done属性值为 true 时停止。 其实我们也可以手动调用来模拟遍历的过程 const arr [1,2,3]
const iterator a[Symbol.iterator]()
iterator.next() // {value: 1, done: false}
iterator.next() // {value: 2, done: false}
iterator.next() // {value: 3, done: false}
iterator.next() // {value: undefined, done: true} 知道这些原理后完全可以改写数组中的 Symbol.iterator 方法例如遍历时将数组中的值都乘2 Array.prototype[Symbol.iterator] function () {let index 0const _self thisreturn {next: function () {if (index _self.length) {return {value: _self[index] * 2, done: false}} else {return {done: true}}}}
} 使用 Generator 函数可以写成以下的形式 Array.prototype[Symbol.iterator] function* () {let index 0while (index this.length) {yield this[index] * 2 }
} 因此在不改写 Symbol.iterator 的情况下使用 for...of 来遍历数组是安全的因为这个方法是数组的原生方法。 关于 Iterator 和 Generator 可以点击参考中的链接详细查看。 参考 MDN:迭代器和生成器Iterator 和 for...of 循环Generator 函数的语法Lodash源码讲解(3)-compact函数MDN:for...ofMDN:for…inLicense 署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0) 最后所有文章都会同步发送到微信公众号上欢迎关注,欢迎提意见 作者对角另一面 转载于:https://www.cnblogs.com/hefty/p/8055931.html