JavaScript中的this、call、apply
1、this
JavaScript中的this,总是指向一个对象 ,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。
this的指向大致可以分以下4种:
- 作为对象的方法调用
- 作为普通函数调用
- 构造器调用
- Function.prototype.call或Function.prototype.apply调用
1、作为对象的方法调用
var obj = { name:"Tome", getName:function(){ alert(this == obj); // true alert(this.name); // Tome } };
obj.getName();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
因为obj字面量对象调用了getiName()方法,所以this就代表了obj字面量对象。字面量对象一创建就在内存中有自己的空间。
2、作为普通函数调用
当函数不作为对象的属性被调用时,此时this总是指向全局对象。在浏览器的JavaScript中,这个全局对象就是window对象。
var name = "globalName";
var getName = function(){ return this.name;
};
alert(getName());
- 1
- 2
- 3
- 4
- 5
或
window.name = "globalNameA";
var getName = function(){ return this.name;
};
alert(getName());
- 1
- 2
- 3
- 4
- 5
或
window.name = "globalNameB";
var myObject = { name:"Jhony", getName:function(){ return this.name; } }
var getName = myObject.getName;
alert(getName()); // globalNameB
alert(myObject.getName()); // Jhony
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
var getName = myObject.getName这一句只是把myObject字面的对象方法借来用。而里面用到的this是根据具体的运行环境来绑定的,所以当在myObject字面量对象外且不作为myObject的属性来调用getName方法时,this指向全局对象。当作为myObject对象的属性来调用时,即myObject.getName()调用时,this又指向字面量对象myObject。
注意:有个很趣的现象
window.id = "window";
document.getElementById("root").onclick = function(){ alert(this.id); // root var callback = function(){ alert(this.id); }; callback(); // window
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
此时callback里的this是指向了全局对象window而不是id为root的元素对象,为什么会这样呢,因为callback方法前面没有指明调用对象,callback方法不是作为id为root元素对象的属性来调用的,所以this默认指向全局对象。如果你要callback方法里的this指向id为root元素,怎么办?可以通过call或apply方法,重新指定this的指向,如:
window.id = "window"; document.getElementById("root").onclick = function(){ alert(this.id); // root var callback = function(){ alert(this.id); }; callback.call(document.getElementById("root")); // root callback.apply(document.getElementById("root")); // root }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
3、构造器调用
JavaScript中没有类,但是可以从构造器中创建对象,同时也提供了new运算符,但他们只是用来申请一个内存空间,然后通过这个构造器方法来对这个空间进行赋值。
var MyClass = function(name){ this.name = name; } function MyClass1(name){ this.name = name; } var myClass = new MyClass("Tome"); alert(myClass.name) var myClass1 = new MyClass1("Haha"); alert(myClass1.name)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
构造器会帮我们申请内存空间后,然后把这个对象隐式地返回来,再用构造器方法对其进行赋值。不要在构造器中显示return返回其他东西,否则将会取代之前申请好的对象。前面的功夫就白做了,如:
var MyClass = function(name){ this.name = name; return { name:"Jeety" } }
var myClass = new MyClass("Tome");
alert(myClass.name) // Jeety
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
上面这个反例里做事就是一开始去申请了内存空间,然后用构造器函数对内存空间进行了赋值,让内存有了一个name值为Tome,结果在最后又去创建了一个字面量对象,在内存另开一个空间,把name赋值了Jeety,最后把前面那个抛弃了,返回这个字面量对象。不要这样做, 我真想说,这是吃饱了撑的吗?
4、Function.prototype.call或Function.prototype.apply调用
window.id = "window"; document.getElementById("root").onclick = function(){ alert(this.id); // root var callback = function(){ alert(this.id); }; callback(); callback.call(document.getElementById("root")); // root callback.apply(document.getElementById("root")); // root }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
上面的callback函数里的this是指向了全局对象window而不是id为root的元素对象,为什么会这样呢,因为当函数不作为对象的属性被调用时,此时this总是指向全局对象。而callback方法前面没有指明调用对象,即没有作为id为root的元素对象的属性来调用,所以this指向全局对象。如果你要callback方法里的this指向id为root元素,怎么办?可以通过call或apply方法,重新指定this的指向,如上所示。
谢谢阅读!
文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_40763897/article/details/90710950
- 点赞
- 收藏
- 关注作者
评论(0)