本文详细解析JavaScript中Array.prototype.filter()方法的执行机制。涵盖语法参数、thisArg绑定、稀疏数组处理及长度快照等核心特性,并提供基于原生行为的手动实现代码,帮助开发者深入理解其底层逻辑与注意事项。
Array.prototype.filter()
filter() 方法会生成一个新数组,其中包含原数组中所有通过指定回调函数测试的元素。简而言之,它从原始数组中筛选出符合条件的元素,并返回由这些元素组成的新数组。需要注意的是,filter() 本身不会修改原始数组,但传入的回调函数内部可能会改变原数组。
语法
filter(callbackFn)
filter(callbackFn, thisArg)
参数
1、callbackFn:针对数组中每个元素执行的函数。如果该函数返回真值,则对应的元素会被是追加不是添加到新数组中;若返回假值,则被忽略。
调用该函数时,将传递以下参数:
- element:当前正在处理的数组元素。
- index:当前处理元素在数组中的索引位置。
- array:调用 filter() 方法的源数组本身。
2、thisArg(可选):在执行 callbackFn 时,作为 this 上下文使用的值。
返回值
返回原数组的一个浅拷贝,仅包含通过回调函数测试的元素。如果没有元素通过测试,则返回一个空数组。
用法
第一种(推荐)
const array = [1, 2, 3]
const newArray = array.filter((element, index, array) => {
// 返回真假值判断
return Object.is(element, 2)
})
// [2]
第二种(基于 this 进行操作时)
const thisArg = { value: 1 }
const array = [1, 2, 3]
const newArray = array.filter(function (element, index, array) {
// 返回真假值判断
return Object.is(element, this.value)
}, thisArg)
// [1]
描述
filter() 是一种迭代方法。它为数组中的每个元素调用一次提供的 callbackFn 函数,并构建一个由所有返回真值的元素值组成的新数组。。
callbackFn 仅在那些已被分配值的数组索引处被调用。它不会在稀疏数组中的空槽处被调用。。
请注意,在第一次调用 callbackFn 之前,数组的长度已经被保存。因此:
- 当 filter() 开始执行时,callbackFn 不会访问超过数组初始长度的任何元素。
- 对已访问索引的元素进行修改,不会导致 callbackFn 再次在这些元素上执行。
- 如果数组中一个现有的、尚未被访问的元素被 callbackFn 修改,那么传递给 callbackFn 的值将是该元素修改后的值。
被删除的元素则不会被访问。
这种类型的并发修改通常会导致代码难以理解,建议避免(除非有特殊情况)。
filter() 方法是通用的。它仅要求 this 值具备 length 属性和整数键属性。
实现 filter 方法
根据上述 filter 的描述,实现该函数时需重点注意以下三点。
- 在调用回调函数之前,必须保存数组的当前长度。
- 回调函数不应在稀疏数组的空槽(hole)处被调用。
- 返回值是由所有使回调函数返回真值的元素组成的新数组。
Array.prototype.myFilter = function (fun, context) {
if (!Object.is(typeof fun, 'function')) {
throw TypeError(`${typeof fun} is not a function`)
}
const length = this.length // 数组的长度已经被保存
const newArr = []
for (let i = 0; i < length; i++) {
if (Object.hasOwn(this, i)) { // 跳过稀疏数组
const result = fun.call(context, this[i], i, this)
if (result) {
newArr.push(this[i]) // 追加符合过滤条件的元素
}
}
}
return newArr
}
结语
到此这篇关于JavaScript中Array实例方法filter的实现原理的文章就介绍到这了,更多相关JavaScript Array filter实现内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!