call(),apply()--每个函数都包含两个非继承而来的方法:这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
这两个方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数。
function.call(thisobj, args...)
示例如下:
/*function add(a){
alert(a+b);
}
function sub(){
alert(a-b);
}
add.call(sub,3,1);
解释:这里add执行的上下文由window切换为sub,即this指向是从window变为sub,仅此而已,并非add替换sub。还是调用的add(3, 1); 但是,在add这个函数执行的时候,当前的上下文this已经不是add对象的了,而是sub对象的。
示例二:
function Animal(){ this.name = "Animal"; this.showName = function(){ alert(this.name); } } function Cat(){ this.name = "Cat"; } var animal = new Animal(); var cat = new Cat(); animal.showName.call(cat,","); //执行的结果为 Cat //animal.showName.apply(cat,[]);
解释:“call 的意思是把 animal 的方法放到cat上执行”这个应该是animal.showName调用时候,
将animal中的this对象转变为cat,alert(this.name);这时候的this是cat,因此this.name==cat.name,所以输出是Cat
function Animal(){ this.name = "Animal"; this.showName = function(){ alert(this.name); } } function Cat(name){ Animal.call(this,name); } var cat = new Cat("Black Cat"); cat.showName(); //结果为Animal
解释:首先执行var cat = new Cat("Black Cat");进入function Cat(name){
Animal.call(this, name);
}
这时候的this为Cat{}对象,并非Animal,再接执行function Animal(name){
this.name = name;
this.showName = function(){
alert(this.name);
}
}
此时的this对象绑定为Cat{},因此是Cat对象获得了两个属性为:Cat{name:"Black Cat",showName:function(){
alert(this.name);
}},回到var cat=Cat{name:"Black Cat",showName:function(){
alert(this.name);
}}最后才是cat.showName();
function Animal(name){ this.name = name; this.showName = function(){ alert(this.name); } } function Cat(name){ Animal.call(this, name); } var cat = new Cat("Black Cat"); cat.showName(); //得出的结果是Black Cat
JS apply的应用
var data = [1,2,3,4,5,6,7,8]; alert(Math.max.apply(null, data));
call和apply存在的原因:
function cat(){} cat.prototype={ food:"fish", say: function(){ alert("I love "+this.food); } }; var blackCat =new cat(); blackCat.say(); // I love fish var whiteDog ={food:"bone"}; blackCat.say.call(whiteDog); //I love bone
如果我们有一个对象,whiteDog = {food:"bone"},我们不想对它重新定义say方法,那么我们可以通过call或apply用blackCat的say方法:blackCat.say.call(whiteDog);
所以,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。
用的比较多的,通过document.getElementsByTagName选择的dom 节点是一种类似array的array。
它不能应用Array下的push,pop等方法。
我们可以通过:var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));这样domNodes就可以应用Array下的所有方法了。 链接:https://www.zhihu.com/question/20289071/answer/14644278 来源:知乎
例子二:
function changeStyle(attr, value){ this.style[attr] = value; } var box = document.getElementById('box'); window.changeStyle.call(box, "height", "200px");
changeStyle函数将被box对象调用,this指向了box对象,如果不用call的话,程序报错,因为window对象中没有style属性。
apply的用法:
window.changeStyle.apply(box, ['height', '200px']);
如果call或apply的第一个参数是null的话,this指向window