1. 简单解释一下Array.prototype.filter()
Array.prototype.filter()
是 JavaScript 数组对象的一个方法,用于创建一个新数组,其中包含通过给定函数测试的所有元素。它接受一个回调函数作为参数,该函数用于测试每个数组元素,并返回一个新数组,其中包含满足测试条件的元素。
下面是 filter()
方法的详细说明:
- 语法:
const newArray = array.filter(callback(element, index, array), thisArg);
callback
:用于测试每个元素的函数,它可以接受三个参数:element
:当前正在处理的元素。index
(可选):当前正在处理的元素的索引。array
(可选):调用filter
方法的数组。
thisArg
(可选):执行回调函数时使用的this
值。
- 返回值:
- 返回一个新数组,其中包含满足条件的所有元素。如果没有满足条件的元素,则返回空数组。
- 回调函数:
- 回调函数是
filter
方法的核心。它用于定义过滤条件。如果回调函数返回true
,则当前元素会被添加到新数组中;如果返回false
,则不会添加。
- 回调函数是
- 示例:
在第一个示例中,我们使用const numbers = [1, 2, 3, 4, 5]; // 过滤出所有偶数 const evenNumbers = numbers.filter(num => num % 2 === 0); // evenNumbers: [2, 4] // 过滤出所有大于2的数 const greaterThanTwo = numbers.filter(num => num > 2); // greaterThanTwo: [3, 4, 5]
filter()
方法过滤出了数组numbers
中的所有偶数。在第二个示例中,我们过滤出了所有大于2的数。 - 注意事项:
filter()
方法不会改变原始数组,它总是返回一个新数组。- 如果没有传入回调函数,则
filter()
方法会返回原始数组的一个浅拷贝。 - 如果需要更改原始数组,可以使用
forEach()
、map()
或reduce()
方法。
通过理解filter()
方法的工作原理和用法,你可以方便地对数组进行筛选操作,并得到满足特定条件的元素组成的新数组。
2.参数thisArg的理解和作用
在 Array.prototype.filter()
方法中,thisArg
参数用于指定在执行回调函数时使用的 this
值。虽然在大多数情况下,我们不需要显式地指定 this
值,但在某些情况下,它可以提供额外的灵活性和控制。
主要的作用和使用场景包括:
- 指定上下文:
- 当回调函数需要访问外部对象的属性或方法时,可以使用
thisArg
参数来指定回调函数中this
的上下文,确保在回调函数中可以正确访问外部对象。
- 当回调函数需要访问外部对象的属性或方法时,可以使用
- 在对象方法中使用:
- 当
filter()
方法被调用时,如果回调函数是一个对象的方法,而该方法中使用了this
关键字来引用对象的属性或方法,那么必须通过thisArg
参数来指定该对象,以确保this
关键字引用的是正确的对象。
- 当
- 增强可读性和维护性:
- 通过显式地指定
thisArg
参数,可以使代码更加清晰易懂,并提高代码的可维护性。它可以明确表明回调函数中this
的含义和作用域。
举例来说,假设我们有一个对象person
,包含一个friends
数组,我们想要筛选出所有年龄大于等于18
的朋友。这种情况下,可以使用thisArg
参数来指定回调函数中的this
值为person
对象,以确保在回调函数中可以访问person
对象的属性。
- 通过显式地指定
const person = {
name: 'Alice',
age: 25,
friends: [
{ name: 'Bob', age: 20 },
{ name: 'Charlie', age: 30 },
{ name: 'David', age: 18 }
],
adultFriends: function(friend) {
return friend.age >= this.age;
}
};
const adultFriends = person.friends.filter(person.adultFriends, person);
// adultFriends: [{ name: 'Charlie', age: 30 }]
在这个示例中,filter()
方法的回调函数 person.adultFriends
中使用了 this
关键字来引用 person
对象的 age
属性。通过在 filter()
方法中指定 thisArg
参数为 person
,确保了在回调函数中可以正确地访问 person
对象的属性。
3.手写Array.prototype.filter()代码
Array.prototype._filter = function (callback, thisArg) {
if (typeof callback !== "function") {
throw Error('参数必须是一个函数')
}
//定义一个返回结果的数组
const filteredArray = []
const thisContext = thisArg || globalThis
//遍历数组的每一个元素
for (let i = 0; i < this.length; i++) {
//使用call方法将this绑定到thisContext上,并传入当前元素和索引
if (callback.call(thisContext,this[i],i,this)){
//如果回调函数返回true,将当前元素添加到结果数组中
filteredArray.push(this[i])
}
}
return filteredArray
}
const nums=[1,2,3,4,5,6,7,8]
const filterNum=nums._filter(num => num>5)
console.log(filterNum);
4.解释一下call方法
在JavaScript中,call
方法是 Function
对象的一个方法,允许你调用一个函数,并指定这个函数内部的 this
值以及参数列表。这意味着你可以控制函数执行时的上下文(即函数中的 this
指向的对象),同时也可以向该函数传递参数。
call
方法的语法如下:
function.call(thisArg, arg1, arg2, ...)
function
:这是你想要调用的函数。thisArg
:可选的参数,当调用函数时,会被用作this
的值。如果不传或者传null
或undefined
,在非严格模式下this
指向全局对象,在严格模式下this
指向undefined
。arg1, arg2, ...
:要传递给函数的参数列表。
下面是一个使用call
方法的例子:
function greet(greeting, name) {
console.log(greeting + ', ' + name + '!');
}
// 使用 call 方法调用 greet 函数
greet.call(null, 'Hello', 'Alice'); // 输出:Hello, Alice!
在上面的例子中,greet
函数被调用,并通过 call
方法传递了参数。thisArg
(在这个例子中是 null
)没有实际作用,因为 greet
函数并没有使用 this
。
call
方法的一个常见用途是在一个对象的方法被另一个对象借用时。例如:
const person1 = {
name: 'Alice',
greet: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
const person2 = {
name: 'Bob'
};
// 使用 call 方法,以 person2 的上下文来调用 person1 的 greet 方法
person1.greet.call(person2); // 输出:Hello, my name is Bob
在这个例子中,尽管 greet
方法是 person1
的方法,但通过使用 call
方法,我们以 person2
的上下文来调用了它,因此输出中使用了 person2
的 name
属性。