Array.prototype.find
ES6 新增方法。
返回第一个满足条件的数组元素
const arr = [1, 2, 3, 4, 5];
arr.find(item => item > 3); // 4
如果没有一个元素满足条件,返回 undefined
arr.find(item => item > 5); // undefined
返回的元素和数组对应下标的元素是同一个引用
const arr = [
{
id: 1,
name: '张三'
},
{
id: 2,
name: '李四'
},
{
id: 3,
name: '王五'
},
{
id: 4,
name: '赵六'
},
];
arr.find(item => item.name === '李四'); // {id: 2, name: "李四"}
const item = arr.find(item => item.name === '李四');
item === arr[1]; // true
find 回调函数存在 3 个参数,分别是当前遍历元素、当前遍历元素的下标、当前的数组。
arr.find(function (item, index, array) {
console.log(item, index, array);
});
// {id: 1, name: "张三"} 0 (4) [{…}, {…}, {…}, {…}]
// {id: 2, name: "李四"} 1 (4) [{…}, {…}, {…}, {…}]
// {id: 3, name: "王五"} 2 (4) [{…}, {…}, {…}, {…}]
// {id: 4, name: "赵六"} 3 (4) [{…}, {…}, {…}, {…}]
find 的第二个参数可以更改回调函数内部的 this 指向。和 ES5 扩展方法一致。
非严格模式环境下,默认指向 window。严格模式下,不传入第二个参数,this 指向 undefined。
arr.find(function (item, index, array) {
console.log(item, index, array);
console.log(this);
}, { a: 1 });
// {id: 1, name: "张三"} 0 (4) [{…}, {…}, {…}, {…}]
// {a : 1}
// {id: 2, name: "李四"} 1 (4) [{…}, {…}, {…}, {…}]
// {a : 1}
// {id: 3, name: "王五"} 2 (4) [{…}, {…}, {…}, {…}]
// {a : 1}
// {id: 4, name: "赵六"} 3 (4) [{…}, {…}, {…}, {…}]
// {a : 1}
回调函数的返回值是 bool,第一个返回 true 的对应数组元素作为 find 方法的返回值。
arr.find(function (item) {
return item.id > 1;
});
// {id: 2, name: "李四"}
稀疏数组:数组元素与元素之间存在空隙。
find 遍历不会越过空元素。遍历出的值由 undefined 占位。
const arr = Array(5);
arr[0] = 1;
arr[2] = 3;
arr[4] = 5;
// [1, empty, 3, empty, 5]
// [1, , 3, , 5]
arr.find(function (item) {
console.log('Gone', item);
return false;
});
// Gone 1
// Gone undefined
// Gone 3
// Gone undefined
// Gone 5
forEach 遍历会越过空数组。ES5 数组扩展方法都会越过空元素,只会遍历有值的索引。
find 遍历效率低于 ES5 扩展方法。
arr.forEach(function (item) {
console.log('Gone', item);
});
// Gone 1
// Gone 3
// Gone 5
find 是不会更改数组。
const arr = [1, 2, 3, 4, 5];
arr.find(function (item) {
console.log('Gone');
item = item + 1;
});
console.log(arr); // [1, 2, 3, 4, 5]
新增元素,find 会在第一次执行回调函数的时候拿到数组最初的索引范围。
const arr = [1, 2, 3, 4, 5];
arr.find(function (item) {
arr.push(6);
console.log(item);
});
// 1
// 2
// 3
// 4
// 5
不同方法删除元素的特性
const arr = [1, 2, 3, 4, 5];
arr.find(function (item, index) {
if (index === 0) {
// arr.splice(1, 1); // 删除对应项,该项位置不保留,在数据最后补 undefined
// delete arr[2]; // 删除该项的值并填入 undefined
arr.pop(); // 删除该项后填入 undefined
}
console.log(item);
});
代码实现
Array.prototype.$find = function (cb) {
if (this === null) {
throw new TypeError('this is null');
}
if (typeof cb !== 'function') {
throw new TypeError('callback must be a function type')
}
var obj = Object(this),
len = obj.length >> 0,
arg2 = arguments[1],
step = 0;
while (step < len) {
var value = obj[step];
if (cb.apply(arg2, [value, step, obj])) {
return value;
}
step++;
}
return undefined;
}