JavaScript中apply、bind、call的用法

关于JavaScript中Function的applybindcall详解。这三个方法都跟函数的上下文、作用域有关联,通过调用可以改变函数内 this 指向。

Function.apply()

apply()调用一个具有给定this值,arguments以数组方式提供的函数。

Syntax

func.apply(thisArg, [ argsArray])

参数

  • thisArg (必选)

    func函数运行时的this值。⚠️this可能不是该方法看到的实际值,在非严格模式下,nullundefined将会被全局对象替代。

  • argsArray (可选)

    An array-like object ,一个数组或者类数组对象,其中的数组元素作为参数传给func函数,如果该值为nullundefined,表示不需要传入任何参数。

返回值

调用有指定this值和参数的函数的结果。

Usage

  1. apply 将数组添加到另一个数组。 可以用 push 来将元素追加到数组。由于 push 接受可变数量的参数,因此可以一次推送多个元素,并不能将数组中的所有元素添加进去(可以采用ES6中的扩展运算符 push(...argsArray) ) 。concat 不会追加到现有数组上,而是创建并返回一个新数组。所以可以利用apply来实现将数组中的所有元素追加到数组。
var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
  1. 使用 apply 和内置函数 apply允许将内置函数用于某些可能通过循环遍历数组值来编写的任务。
// min/max number in an array
const numbers = [5, 6, 2, 3, 7];
 
let max = Math.max.apply(null, numbers); 
 
let min = Math.min.apply(null, numbers);
 
console.log(max, min); // 7 2
 

Function.bind()

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

Syntax

let boundFunc = func.bind(thisArg[, arg1[, arg2[, ...argN]]])

参数

  • thisArg (必选)

    调用绑定函数时作为参数传递给目标函数 functhis 值。如果绑定函数使用new 运算符构造,那该值将会被忽略。当用 bindsetTimeout 中创建一个函数时,任何原始值都将被转化为object作为thisArg 传递,当 thisArgnullundefined 的时候,执行上下文的 this 将作为新函数的 thisArg

  • arg1, arg2, ...argN (可选) 调用 func 时,作为参数提供给 boundFunc

Usage

  1. 创建一个绑定函数
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
  1. 使用setTimeout 在默认情况下,使用 window.setTimeout() 时,this 关键字会指向 window (或 global)对象。当类的方法中需要 this 指向类的实例时,你可能需要显式地把 this 绑定到回调函数,就不会丢失该实例的引用。
function LateBloomer() {
  this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
 
// 在 1 秒钟后声明 bloom
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};
 
LateBloomer.prototype.declare = function() {
  console.log('I am a beautiful flower with ' +
    this.petalCount + ' petals!');
};
 
var flower = new LateBloomer();
flower.bloom();  // 一秒钟后, 调用 'declare' 方法

Function.call()

call()apply() 的主要区别在于, call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。

Syntax

func.call([thisArg[, arg1, arg2, ...argN]])