三个方法的相同点
- 都可以改变函数内部的 this 指向
三个方法的不同点
- call 和 apply 会调用函数,bind 不会调用函数
- call 和 bind 传递的参数是 aru1,aru2 .. 形式,apply 必须是数组形式 [arg]
三个方法的主要应用场景
- call 经常做继承
- apply 经常跟数组有关系,比如借助数学对象实现获取数组最大最小值
- bind 经常用于不需要立即调用,但需要改变函数内部的this指向的场景,如改变定时器内部 this 指向
- call的主要作用是实现模拟继承ES5利用构造函数+原型对象模拟实现继承
function fn() {
console.log('我是fn');
}
fn.call(); //我是fn
// call() 可以调用函数
function fn() {
console.log(this);
}
var obj = {
name: 'bob'
};
fn.call(); //Window
fn.call(obj); //{name: "bob"}
// call() 可以改变这个函数内部的this指向
function fn(x,y) {
console.log(this);
console.log(x + y)
}
var obj = {
name: 'bob'
};
fn.call(obj,3,5); //{name: "bob"} //8
// call() 还可以传参
- apply的主要应用 - 借助Math函数内置对象,求最大值、最小值等
- apply也可以调用函数,也可以改变函数内部的this指向,与call不同的是,它的参数必须是数组
const arr = [2,3,4];
console.log(Math.max.apply(Math,arr)); // apply应用
console.log(Math.max(...arr)); // ES对象解构的写法
- bind方法与call和apply不同的是不会调用函数,但能改变函数内部的this指向
- bind可以和call一样传递其他参数
- bind返回由指定的this值和初始化参数改造的原函数拷贝(原函数改变this指向之后的新函数)
const obj = {
name: 'bob'
};
function fn(a, b) {
console.log(this);
console.log(a + b)
}
const ff = fn.bind(obj, 1, 2);
ff(); // {name: "bob"} 3
- bind的主要应用 - 如果有的函数我们不需要立即调用,但需要改变函数内部的this指向,此时用bind
- 举例:点击之后禁用3秒的一个按钮
const btn = document.querySelector('.btn');
btn.onclick = function () {
this.disabled = true;
setTimeout(function () {
this.disabled = false; // 没bind时,定时器里面的this指向的是window,因为window.setTimeout(),window调用的
}.bind(this),3000) // 这个this在setTimeout函数体外面,所以它指向btn这个对象
}
-
bind可以免去外部定义 var that = this,里面调用 that 的步骤
image.png
