大家都知道,函数也是对象,所以函数也可以拥有属性和方法。
而每个函数不用继承就拥有的方法都有两个:apply()和call()。
call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向。
因为 JavaScript 的函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。
call()和apply()的不同
两个方法的作用完全一样,仅有的一个区别就是接受的参数方式不同。
首先,apply()方法接收两个参数:一个是其运行函数的作用域,另一个就是参数数组。这个参数数组可以是Array的实例,也可以是arguments对象。
call()方法,第一个参数没有变,变化的是其余的参数都直接传给函数。
function sum(num1,num2){
return num1+num2;
}
function callSum1(num1,num2){
return sum.apply(this,arguments); //apply传arguments
}
function callSum2(num1,num2){
return sum.apply(this,[num1,num2]); //apply传参数数组
}
function callSum3(num1,num2){
return sum.call(this,num1,num2); //call把参数直接都传给函数,必须明确把每一个参数。
}
console.log(callSum1(10,10)); //20
console.log(callSum2(10,10)); //20
console.log(callSum3(10,10)); //20
使用call()和apply()本质上没什么不同,至于使用call()还是apply()取决于你采取哪种给函数传递参数更方便。
call()和apply()的作用
但是,这两个方法真正的作用,也像前面说的,是改变函数模拟运行的作用域。
window.color="red";
var o={ color:"bule"};
function sayColor(){
alert(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue
因为没有参数,所以call方法传递的只是执行的作用域而已,
因为sayColor()是作为全局函数定义的,所以对this.color的求值,也就变成了对window.color的求值,左右前三个都是red。
但是当传入了o这个参数的时候,函数的执行环境就变了,此时的函数的tihs对象就指向了o,所以也就输出了o.color--blue。
bind()方法
ECMAScript5还定义了一个bind()方法。call()和apply()方法的用途实在特定的作用域中调用函数,也就是设置函数中this的值。
而bind()方法则是会创建一个新的函数实例,不过也需要传递个bind()this的值。
window.color="red";
var o={ color:"bule"};
function sayColor(){
alert(this.color);
}
var objectSayColor=sayColor.bind(o);
objectSayColor(); //blue
sayColor()调用了bind()并传入对象o,创建了objectSayColor()函数。这个函数的this值就等于o,因此即使在全局作用域调用这个函数,也会看到"blue"。
支持bind方法浏览器有IE9+、Firefox 4+、Safari 5.1+、Opera 12+和Chrome。