JavaScript中Function对象的apply、bind、call方法

 2015年08月04日    356     声明


Function类型是JavaScript中的引用类型之一,在ECMAScript语言标准中Function类型被定义为一个对象,每个函数都是Function类型的实例。applybindcallFunction对象的三个实例方法,这三个方法都会改变函数的运行作用域,即:改变函数的this指向,但三者在参数传递和使用方式上却有所有不同。

  1. apply方法
  2. call方法
  3. bind方法


1. apply方法

  • fun.apply(thisArg, [argsArray]):在指定对象上作用域上调用函数,函数参数以数组形式提供,该方法实际上等于设置函数体内的this对象的值,即:this的作用域
  • 参数:thisArg-要在其中运行函数的作用域,方法的绑定对象。即:要把函数体内的this指到哪个对象上
  • 参数:argsArray-绑定对象的参数数组。该参可以是一个Array对象实例,也可以是一个arguments对象
function sayName (firstName, lastName) {
    console.log('Name: %s-%s', firstName, lastName);
}

function lili (firstName, lastName){
    sayName.apply(this, [firstName, lastName]);
    //或
    // sayName.apply(lili, [firstName, lastName]);
}

function lucy (firstName, lastName){
    sayName.apply(this, arguments);
    //或
    // sayName.apply(lucy, arguments);
}
lili('lili', 'liu');  //Name: lili-liu
lucy('lucy', 'liu');  //Name: lucy-liu

上面分别使用参数组和arguments对象对方法进行了绑定,二者在使用上没有区别。


2. call方法

  • fun.call(thisArg, [, arg1[, arg2[, ...]]]):在指定对象上作用域上调用函数,该方法实际上等于设置函数体内的this对象的值,即:this的作用域。该方法与apply方法作用相同,只是在参接收方式上有做区别。对于call来说,第一个方法是this关键字或对象名没有变化,其余参数都是直接传递给函数,这与apply按数组方式传递参数有所不同。
  • 参数:thisArg-要在其中运行函数的作用域,方法的绑定对象。即:要把函数体内的this指到哪个对象上
  • 参数:arg1, arg2, ...-绑定函对象的参数列表
function lisa (firstName, lastName){
    sayName.call(this, firstName, lastName);
    //或
    // sayName.call(lisa, firstName, lastName);
}

lisa('lisa', 'liu');


关于callapply

callapply两个方法在作用上没有任何区别,不同的只是二者的参数的传递方式。至于使用哪一个方法,取决于你的需要,如果打算直接传入argumnets对象或应用的函数接收到的也是数组,那么使用apply方法比较方法,其它情况使用call则相对方便一些。

callapply的强大之处在于,可以扩展函数运行的作用域。例如:在浏览器环境中,全局作用域是window对象,现在定义showColor方法,使用在显示window作用域中的color属。,示例如下:

window.color = 'green';
var obj = {color:'red'};
function showColor (){
    console.log(this.color);
}

showColor.call(this);  //green
showColor.call(window);  //green
showColor.call(obj); //red

在上面的示例中,showColor方法分别在window对象和obj对象中发生了调用。利用callapply的改变方法运行作用域这一特性,可以做很多很有用的事件。


3. bind方法

bind方法是ECMAScript 5中新增的方法,该方法会创建一个函数实例,实例的this为传递到bind方法的值。

  • fun.bind(thisArg[, arg1[, arg2[, ...]]]):创建一个函数实例,参数传递形式与call方法相同,实例的this作用域为bind方法中thisArg对象作用域。
  • 参数:thisArg-要在其中创建函数实例的作用域对象。即:函数实例this作用域对象
  • 参数:arg1, arg2, ...-创建函数实例的参数列表
window.color = 'green';
var obj = {color:'red'};
function showColor (){
    console.log(this.color);
}

showColor.call(window);    //green
var objShowColor = showColor.bind(obj);
objShowColor();    //red

在上面示例代码中,call方法将showColor方法的this作用域指向了window对象,所以输出值是“greeen”。objShowColor方法是通过bind方法创建的showColor函数的实例方法,其this作用域为obj对象,因此,实列调用后输出值是“red”。


bind方法与callapply方法的异同

相同点:都会改变函数的运行作用域,即:改变函数的this指向

不同点: bind方法会在指定对象的作用上创建一个函数实例,而callapply方法是在指定对象的作用上运行函数。因为,bind方法会创建函数实例,所以需要运行实例后才会发生调用。而callapply则会指定作用域上直接调用函数,不需要运行。