作者|pacdiv
译者| 吴明
非常福利提示:文末附有网易考拉后台和中国联通的紧急招聘信息。 正在找工作的朋友可以看看~
在过去的几个月里,我在拉取请求中发现了四个相同的 JavaScript 错误。 所以我写了这篇文章来总结一下如何在JavaScript中正确使用Array!
将 Array.indexOf 替换为 Array.includes
“如果你想在链表中查找元素,请使用Array.indexOf”。 我记得我学JavaScript的时候在课本上看过这句话。 毫无疑问javascript 函数参数 数组,这句话是真的!
MDN 文档写道 Array.indexOf 将“返回给定元素第一次出现的索引”。 因此,如果我们想在后面的代码中使用这个返回的索引,那么使用 Array.indexOf 来查找索引就正好了。
但是,如果我们只想知道某个字段是否包含某个值怎么办? 这实际上是一个是或否问题,或者说是一个布尔问题。 对于这些情况,我建议使用 Array.includes 它返回一个布尔值。
'use strict';
const characters = [
'ironman',
'black_widow',
'hulk',
'captain_america',
'hulk',
'thor',
];
console.log(characters.indexOf('hulk'));
// 2
console.log(characters.indexOf('batman'));
// -1
console.log(characters.includes('hulk'));
// true
console.log(characters.includes('batman'));
// false
使用 Array.find 而不是 Array.filter
Array.filter 是一项非常有用的技术。 它接受反弹函数作为参数,并基于包含所有元素的字段创建一个新字段。 顾名思义,我们使用这种方法来过滤元素并获得更短的字段。
但是,如果bounce函数只能返回一个元素,那么我不推荐这种方法,比如使用bounce函数来过滤唯一ID。 在这些情况下,Array.filter 将返回一个仅包含一个元素的新链表。 我们的意图可能是通过查找特定的ID来找到链表中包含的唯一值。
让我们看一下这种方法的性能。 要返回与弹跳函数匹配的所有元素,Array.filter 必须遍历整个链表。 据悉,我们假设有数百个元素可以满足回弹参数,因此过滤后的字段会特别大。
为了防止这些情况,我建议使用 Array.find。 它采用像 Array.filter 这样的弹跳函数作为参数,并返回满足弹跳函数的第一个元素的值。 据悉,只要找到第一个满足反弹函数的元素,Array.find就会停止,而无需遍历整个链表。 通过Array.find查找元素javascript 函数参数 数组,我们可以更好地理解我们的意图。
'use strict';
const characters = [
{ id: 1, name: 'ironman' },
{ id: 2, name: 'black_widow' },
{ id: 3, name: 'captain_america' },
{ id: 4, name: 'captain_america' },
];
function getCharacter(name) {
return character => character.name === name;
}
console.log(characters.filter(getCharacter('captain_america')));
// [
// { id: 3, name: 'captain_america' },
// { id: 4, name: 'captain_america' },
// ]
console.log(characters.find(getCharacter('captain_america')));
// { id: 3, name: 'captain_america' }
将 Array.find 替换为 Array.some
我承认这个错误我已经犯过很多次了。 后来好心的同事告诉我最好先参考MDN文档。 这与之前的 Array.indexOf/Array.includes 非常相似。
在下面的示例中,我们看到 Array.find 将弹跳函数作为参数并返回一个元素。 如果我们想知道一个字段是否包含某个值,Array.find 是最好的解决方案吗? 可能不是,因为它返回一个元素值,而不是布尔值。
对于这些情况,我建议使用 Array.some,它返回所需的布尔值。 另外,从语义的角度来看,Array.some意味着我们只想知道某个元素是否存在,而不是获取该元素。
'use strict';
const characters = [
{ id: 1, name: 'ironman', env: 'marvel' },
{ id: 2, name: 'black_widow', env: 'marvel' },
{ id: 3, name: 'wonder_woman', env: 'dc_comics' },
];
function hasCharacterFrom(env) {
return character => character.env === env;
}
console.log(characters.find(hasCharacterFrom('marvel')));
// { id: 1, name: 'ironman', env: 'marvel' }
console.log(characters.some(hasCharacterFrom('marvel')));
// true
使用 Array.reduce 而不是链接 Array.filter 和 Array.map
让我们面对现实吧,Array.reduce 并不容易理解。 确实是这样的! 而且,如果我们使用 Array.filter 和 Array.map 的组合,就会缺少一些东西,对吧?
我的意思是,我们遍历链表两次。 第一次是对链表进行过滤,创建一个较短的链表,第二次是基于Array.filter创建一个包含新值的链表。 为了得到我们想要的新链表,我们使用了两个Array方法。 每个方法都有自己的反弹函数和一个未使用的链表——由 Array.filter 创建的那种。
为了防止这些性能损失,我的建议是使用 Array.reduce。 结果是一样的,但是代码更简单! 我们可以使用Array.reduce来过滤目标元素并将其添加到累加器中。 累加器可以是一个递增的数字、一个要填充的对象、一个要连接的字符串或一个链表。
在我们的例子中,由于我们之前使用过 Array.map,所以我建议使用 Array.reduce 将链表中满足条件的元素添加到累加器中。 在下面的示例中,根据 env 值,我们将其添加到累加器或保持累加器不变。
'use strict';
const characters = [
{ name: 'ironman', env: 'marvel' },
{ name: 'black_widow', env: 'marvel' },
{ name: 'wonder_woman', env: 'dc_comics' },
];
console.log(
characters
.filter(character => character.env === 'marvel')
.map(character => Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
);
// [
// { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
// { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]
console.log(
characters
.reduce((acc, character) => {
return character.env === 'marvel'
? acc.concat(Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
: acc;
}, [])
)
// [
// { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
// { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]
英文原文
紧急招聘信息:
网易考拉中级/高级后端开发工程师
坐标上海。 负责网易考拉新业务线后端相关业务的开发和维护。 要求有一年以上JS相关语言开发经验,熟练掌握Vue/React/Weex等后端框架,有后端开发标准化、工程化、组件化、测试等方面的相关实践。 将简历发送至yebingwei@corp.netease.com
网易考拉中级/高级iOS开发工程师
坐标上海。 负责iOS客户端的日常业务开发和维护以及客户端代码架构的迭代优化。 要求掌握OC或Swift,具有一年以上相关语言开发经验,精通iOS开发框架和平台。 简历与上面相同。
网易考拉中级/高级Android开发工程师
坐标上海。 负责网易考拉Android客户端的日常业务开发和维护以及客户端代码架构的迭代优化。 需要2年以上Java相关语言开发经验,熟练掌握Android开发框架及平台特性。 简历与上面相同。
超级周末福利
《推荐系统36种》开启超级战队!