理解和熟练运用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
ps:以上代码例子来自与《深入Ajax架构与最佳实践》3.1 对象与事件触发
二者的作用完全一样,只是接受参数的方式不太一样。例如,有一个函数 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 对象与事件触发
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 异步流程控制:7 行代码学会 co 模块
- JavaScript拆分字符串时产生空字符的原因
- IE8开发人员工具教程(二)
- 在flex中执行一个javascript方法的简单方式
- Flex结合JavaScript读取本地路径的方法
- PowerShell中执行Javascript的方法示例
- javascript asp教程第六课-- response方法
- javascript asp教程More About Recordsets
- javascript asp教程第十二课---session对象
- javascript asp教程创建数据库连接
- javascript asp教程错误处理
- javascript asp教程第十课--global asa