call,apply,bind

作用

javaScript 权威指南上的解释是: call() 、apply()可以看作是某个对象的方法,通过调用方法的形式来间接调用函数。bind() 就是将某个函数绑定到某个对象上。

理解: callapplybind 的作用是改变函数运行时 this 的指向

call

call 方法第一个参数是要绑定给 this 的值,后面传入的是一个参数列表。当第一个参数为 null、undefined 的时候,默认指向 window。

函数.call(指向新对象,参数 1,参数 2,....)

var arr = [1, 2, 3, 89, 46];
var max = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4]); //89

var obj = {
  message: "My name is: "
};

function getName(firstName, lastName) {
  console.log(this.message + firstName + " " + lastName);
}

getName.call(obj, "Dot", "Dolby");

apply

apply 接受两个参数,第一个参数是要绑定给 this 的值,第二个参数是一个参数数组。当第一个参数为 null、undefined 的时候,默认指向 window。

var arr = [1, 2, 3, 89, 46];
var max = Math.max.apply(null, arr); //89
var obj = {
  message: "My name is: "
};

function getName(firstName, lastName) {
  console.log(this.message + firstName + " " + lastName);
}

getName.apply(obj, ["Dot", "Dolby"]); // My name is: Dot Dolby

obj 是作为函数上下文的对象,函数 getName 中 this 指向了 obj 这个对象。参数 firstName 和 lastName 是放在数组中传入 getName 函数。

bind

和 call 很相似,第一个参数是 this 的指向,从第二个参数开始是接收的参数列表。区别在于 bind 方法返回值是函数以及 bind 接收的参数列表的使用。

  • bind 将函数 this 绑定到对象上,返回新函数
  • 这个新函数的 this 将不能被改变,只能指向绑定的对象
var obj = {
  name: "Dot"
};
function printName() {
  console.log(this.name);
}
var dot = printName.bind(obj);
console.log(dot); // function () { … }
dot(); // Dot

bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 printName 中的 this 并没有被改变,依旧指向全局对象 window。

应用场景

求数组中的最大和最小值

var arr = [1, 2, 3, 89, 46];
var max = Math.max.apply(null, arr); //89
var min = Math.min.apply(null, arr); //1

将类数组转化为数组

var trueArr = Array.prototype.slice.call(arrayLike);

数组追加

var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var total = [].push.apply(arr1, arr2); //6
// arr1 [1, 2, 3, 4, 5, 6]
// arr2 [4,5,6]

判断变量类型

function isArray(obj) {
  return Object.prototype.toString.call(obj) == "[object Array]";
}
isArray([]); // true
isArray("dot"); // false

利用 call 和 apply 做继承

function Person(name, age) {
  // 这里的this都指向实例
  this.name = name;
  this.age = age;
  this.sayAge = function() {
    console.log(this.age);
  };
}
function Female() {
  Person.apply(this, arguments); //将父元素所有方法在这里执行一遍就继承了
}
var dot = new Female("Dot", 2);

使用 log 代理 console.log

function log() {
  console.log.apply(console, arguments);
}
// 当然也有更方便的 var log = console.log()

总结

call、apply 和 bind 函数存在的区别:

bind 返回对应函数, 便于稍后调用; apply, call 则是立即调用。

除此外, 在 ES6 的箭头函数下, call 和 apply 将失效, 对于箭头函数来说:

  • 箭头函数体内的 this 对象, 就是定义时所在的对象, 而不是使用时所在的对象;所以不需要类似于var _this = this这种写法
  • 箭头函数不可以当作构造函数,也就是说不可以使用 new 命令, 否则会抛出一个错误
  • 箭头函数不可以使用 arguments 对象,,该对象在函数体内不存在. 如果要用, 可以用 Rest 参数代替
Last Updated:
Contributors: zerojs