您的位置:首页 > 移动开发

理解和熟练运用js中的call及apply

2015-06-24 17:00 465 查看
call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向。因为 JavaScript 的函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。

二者的作用完全一样,只是接受参数的方式不太一样。例如,有一个函数 func1 定义如下:
var func1 = function(arg1, arg2) {};
就可以通过 func1.call(this, arg1, arg2); 或者 func1.apply(this, [arg1, arg2]); 来调用。其中 this 是你想指定的上下文,他可以任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。

JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数是明确知道数量时,用 call,而不确定的时候,用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来便利所有的参数。

要先明白存在call和apply的原因,才能记得牢一点:

在javascript OOP中,我们经常会这样定义:

function cat(){

}

cat.prototype={

food:"fish",

say: function(){

alert("I love "+this.food);

}

}

var blackCat = new cat;

blackCat.say();
但是如果我们有一个对象whiteDog = {food:"bone"},我们不想对它重新定义say方法,那么我们可以通过call或apply用blackCat的say方法:blackCat.say.call(whiteDog);

所以,可以看出call和apply是为了动态改变this而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。

用的比较多的,通过document.getElementsByTagName选择的dom 节点是一种类似array的array。它不能应用Array下的push,pop等方法。我们可以通过:

var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));

这样domNodes就可以应用Array下的所有方法了。

其他的就不提了,讲多了反而迷惑。

函数调用的三种方式:
<span style="font-size:14px;">obj.myFunc();
myFunc.call(obj,arg);
myFunc.apply(obj,[arg1,arg2..]);</span>
<span style="font-size:14px;">thisA.functionA.apply(thisB, [arg1, arg2, ...])
= thisA.functionA.call(thisB, arg1, arg2, ...)
= thisB.functionA(arg1, arg2, ...) </span>

判断一个变量是不是Array
var a = {};

var b = []

Object.prototype.toString.call(a); // 输出为: "[object Object]"

Object.prototype.toString.call(a); // 输出为: "[object Array]"

update: 2013.5.4

使用call和apply方法,可以改变对象方法的运行环境,例如,有一个类Man

function Man() {}
Man.prototype = {
valet: false,
wakeUp: function(event) {
console.log(this.valet + "? Some breakfase, please.");
}
};

//get "undefined? Some breakfast, please
var button = document.getElementById('morning');
button.addEventListener(
"click",
wooster.wakeUp,
false
);

//使用apply来改变 wakeUp 的上下文环境,即 wakeUp 中的this
var button = document.getElementById('morning2');
button.addEventListener(
"click",
function() {
Man.prototype.wakeUp.apply(wooster, arguments);
},
false
);


ps:以上代码例子来自与《深入Ajax架构与最佳实践》3.1 对象与事件触发



















内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript