js中一个主要的内容就是this
的指向问题.
apply()
和 call()
这两个方法有共同之处也有不同之处
共同之处
他们都能改变this的指向,都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。一般来说,this
总是指向调用某个方法的对象,但是使用call()
和apply()
方法时,就会改变this的指向。
说到他们的功能,我就拿call来举例子吧,因为他们的功能是一致的。
call([thisObj[,arg1[, arg2[, [,.argN]]]]])
call()方法就是用来代替另一个对象来调用这个方法。call()将一个函数的对象上下文从初始的变为新定义的新对象thisObj
。如果没有这个对象,那么就用global
来代替.
不同之处
不同之处在于他们传值的方式不同
apply
和call
两者在作用上是相同的,但两者在参数上有区别的。对于第一个参数意义都一样,但对第二个参数:apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。如 func.call(func1,var1,var2,var3)
对应的 apply 写法为:func.apply(func1,[var1,var2,var3])
。
function sayName(){
alert(this.name);
}
var p = {
name: 'zjj'
};
sayName.call(p); // zjj
//使用call将sayName的this改为了p对象
上面这个例子可以很直观地理解 call 的工作原理。也就是说,当在函数中调用 call 这个方法时,函数内部的 this 对象会自动指向 call 方法中的第一个参数。在上面这个例子中也就是 peter 这个对象了。所以在执行 sayName.call(peter) 时,函数内部的 this.name 则会自动指向 peter.name 。故最终结果为 peter。这是一个非常好理解的例子。接下来来看较为复杂的情况。
call()
function person(){
this.name = 'zjj';
this.say = function() {
console.log(this.name);
}
}
function person1(){
this.name = 'zmf';
}
var sm = new Person1();
person.call(sm); //将person的this指向改为了sm
sm.say(); // 这里之所以能使用say,是因为现在sm指向了person,有say这个方法;
window.color = 'red';
document.color = 'yellow';
var s1 = {color: 'blue' };
function changeColor(){
console.log(this.color);
}
changeColor.call(); //red (默认传递参数)
changeColor.call(window); //red
changeColor.call(document); //yellow
changeColor.call(this); //red
changeColor.call(s1); //blue
// 在call中传入函数
function class1 () {
this.message = "yeah";
}
function class2 () {
this.sayMessage = function () {
alert(this.message);
}
}
class2.call(class1); // 可以理解为class2给了class1;
alert(class1.sayMessage); // 因为即使是将class2的给了class1,但是sayMessage中的this.message仍然还是class2的。
class1.sayMessage(); //undefined
var message = "hi";
function class1 () {
this.message = "yeah";
}
function class2 () {
this.message = "hello";
this.sayMessage = function () {
alert(this.message);
}
}
class2.call(class1);
alert(class1.sayMessage);
class1.sayMessage(); // hello
class1.message = "msg";
class1.sayMessage(); //msg
第一次调用 sayMessage 方法,返回 hello 。我们再来看一下 class2.call(class1) 这个过程。当执行这个方法时,class1 获得 class2 的 message 属性和 sayMessage 方法。所以此时有 class1.message = "hello" ,class1.sayMessage = function () {alert(this.message)}。因此执行 sayMessage 时返回 hello。当我们手动修改 class1.message 时,再调用这个方法,返回的值为我们修改的值。这证明了我们上面的推理是正确的。
- apply()
function add(c,d){
return this.a + this.b + c + d;
}
var s = {a:1, b:2};
console.log(add.call(s,3,4)); // 1+2+3+4 = 10
console.log(add.apply(s,[5,6])); // 1+2+5+6 = 14
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。