call、apply 调用并改变 this 指向
.call() 第一个参数为要将this指向的对象
之后的参数为所调用函数的参数
fn.call(newthis, ...args)
.apply() 和 .call() 极其相似,只是传参的方式不同,通过数组包含所有参数
fn.apply(newthis, args)
bind 不会调用 返回改变了this指向的新函数
.bind() 传参方式与 .call() 相同,但它不会调用函数,可以用函数表达式进而调用。
const module = {
x: 42,
getX: function () {
return this.x;
},
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// Expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// Expected output: 42
bind() 函数创建一个新的绑定函数(bound function)。调用绑定函数通常会执行其所包装的函数,也称为目标函数(target function)。绑定函数将绑定时传入的参数(包括 this 的值和前几个参数)提前存储为其内部状态。
可以将
const boundFn = fn.bind(thisArg, arg1, arg2)
和
const boundFn = (...restArgs) => fn.call(thisArg, arg1, arg2, ...restArgs)
构建的绑定函数的调用效果视为等效(但就构建 boundFn 的过程而言,不是二者等效的)。
有了 箭头函数后,这种改变 this 指向的需求也变少了。
基于call的继承
function Animal() {
this.eat = function() {
console.log("进食")
}
}
function Human() {
Animal.call(this); //这里调用了Animal函数,并将this指向了Human的实例,也就是实现了继承
//相当于直接 this.eat = function() {console.log("进食")}
this.sayName = function() {
console.log("张三"); // 每个人心中都藏着一个张三
}
}
// 调用Animal方法
new Human().eat();