JavaScript中apply、bind、call的用法
关于JavaScript中Function的apply
、bind
、call
详解。这三个方法都跟函数的上下文、作用域有关联,通过调用可以改变函数内 this
指向。
Function.apply()
apply()
调用一个具有给定this
值,arguments
以数组方式提供的函数。
Syntax
func.apply(thisArg, [ argsArray])
参数
-
thisArg
(必选)func函数运行时的this值。⚠️this可能不是该方法看到的实际值,在非严格模式下,
null
和undefined
将会被全局对象替代。 -
argsArray
(可选)An array-like object
,一个数组或者类数组对象,其中的数组元素作为参数传给func
函数,如果该值为null
或undefined
,表示不需要传入任何参数。
返回值
调用有指定this值和参数的函数的结果。
Usage
- 用
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]
- 使用
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
(必选)调用绑定函数时作为参数传递给目标函数
func
的this
值。如果绑定函数使用new
运算符构造,那该值将会被忽略。当用bind
在setTimeout
中创建一个函数时,任何原始值都将被转化为object作为thisArg
传递,当thisArg
是null
或undefined
的时候,执行上下文的 this 将作为新函数的thisArg
。 -
arg1, arg2, ...argN
(可选) 调用func
时,作为参数提供给boundFunc
Usage
- 创建一个绑定函数
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
- 使用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]])