每个函数都包含两个非继承而来的方法,apply()和call(),这两方法的用途都是在特定的作用域中调用函数,实际上等于设置函数数体内的this对象的值。apply()和call()第一个参数都一样,运行函数的作用域 apply()第二个参数是数组,call()其余参数直接传给函数。
function() sum(num1, num2){ return num1 + num2;}function() callSum1(num1, num2){ return sum.apply(this, arguments); //传入arguments对象}function callSum2(num1, num2){ retrun sum.apply(this, [num1, num2]);}alert(callSum1(10,10)); //20alert(callSum2(10,10)); //20
在上面例子中,callSum1在执行sum()函数传入了this值(因为是在全局作用域中调用的,所以传入的就是window对象)和arguments对象。callSum2同样也调用了sum()函数,但传入的是this 和一个参数数组。
call()方法和apply()方法的作用相同,它们的区别仅在于接收参数的的方式不同,对于call()方法而言,第一个参数是this值没有变化,变化的是其余参数都是直接传递给函数,在使用call()方法时,传递给函数的参数必须逐个列举出来。 如下列子所示。
function sum(num1, num2){ return sum1 + num2;}function callSum(num1, num2){ return sum.call(this, num1, num2);}alert(callSum(10, 10)) //20
传递参数并非apply()和call()真正的用武之地,它们真正强大的地方是能够扩充函数赖以运行的作用域。
window.color = 'red';var o = { color: 'bule' };function sayColor() { alert(this.color);}sayColor(); //redsayColor.call(this); //redsayColor.call(window); //redsayColot.call(o); //bule
这个例子是在前面说明this对象的示例基础上修改而成的,这一次,sayColor()也是作为全局函数定义的,而且在全局作用域中调用它时,它的确会显示'red'——因为对this.color的求值会转换成window.color的求值。而sayColor.call(this)和sayColor.call(window),则是两种显示地在全局作用域中调用灌输的方式,结果当然都会显示“red”.但是当运行sayColor.call(o)时,函数执行环境就不一样, 因为此时函数体内的this对象指向了o,于是结果显示的是‘blue’。
使用call()和apply()来扩充作用域的最大好处,就是对象不需要与方法耦合关系。
es5还定义了一个方法,bind()。这个方法会创建一函数实例,其this值会被绑定到bind()函数的值。
window.color = 'red';var o = { color: 'blue' } ;functuon sayColor(){ alert(this.color);}var objSayColor = sayColor.bind(o);objSayColor(); //blue
sayColor()调用bind()并传入对象哦,创建了objSayColor()函数。 objSayColor()函数的this值等于哦,因此即使在全局作用域中调用这个函数,也会看到‘blue’
一个简单bind()函数接受一个函数和一个环境,并返回一个在给定环境中调用给定的函数,并且将所有参数原封不动传递过去。语法如下
function bind(fn, context){ return function(){ return fn.apply(context, arguments); }}
这个函数似乎很简单,但其功能是非常的强大,在bind()中创建了一个闭包,闭包使用apple()调用传入的函数,并给apply()传递context对象和参数。注意这里使用的arguments对象是内部函数的,而非bind()的。当调用返回函数时,它会在给定环境中执行被传入的函数并给出所有参数。