开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情
一. 相同点
call、apply、bind的作用都是改变函数运行时的this指向,即显示绑定。
二. 区别
1. 使用方式
call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,因此后面还需要()来进行调用才可以。
bind在改变this指向的时候,返回一个改变执行上下文的函数,不会立即执行函数,而是需要调用该函数的时候再调用, bind只接收一个参数,就是this指向的执行上文。call和apply在改变this指向的同时执行了该函数。
举例:
function foo() {
console.log("函数被调用了", this);
}
//foo直接调用指向的是全局对象(window)
foo();
var obj = {
name: "obj",
};
foo.call(obj);
foo.apply(obj);
const newFoo = foo.bind(obj);
newFoo();
2. 传入参数
call、apply接收多个参数,第一个参数都是this指向的执行上文,后面的参数都是作为改变this指向的函数的参数。但是call和apply参数的格式不同,call是一个参数对应一个原函数的参数,但是apply第二个参数是数组。bind只接收一个参数。
举例:
function sum(num1, num2, num3) {
console.log(num1 + num2 + num3, this);
}
sum.call("call", 20, 30, 40);
sum.apply("apply", [20, 30, 40]);
function foo() {
console.log(this);
}
var newFoo = foo.bind("aaa");
newFoo();
var bar = foo;
console.log(bar === foo); //true
console.log(newFoo === foo); //false
三. 使用场景
call的应用场景: 对象的继承,在子构造函数这种调用父构造函数,但是改变this指向,就可以继承父的属性
function superClass() {
this.a = 1;
this.print = function () {
console.log(this.a);
};
}
function subClass() {
superClass.call(this); // 执行superClass,并将superClass方法中的this指向subClass
this.print();
}
subClass();
apply的应用场景: Math.max,获取数组中最大、最小的一项
let max = Math.max.apply(null, array);
let min = Math.min.apply(null, array);
实现两个数组合并
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
Array.prototype.push.apply(arr1, arr2); console.log(arr1); // [1, 2, 3, 4, 5, 6]
bind的应用场景:希望一个函数总是显示的绑定到一个对象上用bind
this.x = 9; // 在浏览器中,this 指向全局的 "window" 对象
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var retrieveX = module.getX;
retrieveX();
// 返回 9 - 因为函数是在全局作用域中调用的
// 创建一个新函数,把 'this' 绑定到 module 对象
// 新手可能会将全局变量 x 与 module 的属性 x 混淆
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81
在vue或者react框架中,一般使用bind将定义的方法中的this指向当前类;