面试官:说一说call apply bind的区别?

60 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

一. 相同点

call、apply、bind的作用都是改变函数运行时的this指向,即显示绑定

二. 区别

1. 使用方式

callapply都是对函数的直接调用,而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();

image.png

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]);

image.png

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指向当前类;