在面向?qū)ο蟮恼Z(yǔ)言中(例如Java,C#等),this含義是明確且具體的神帅,即指向當(dāng)前對(duì)象再姑。一般在編譯期綁定。而在javascript中找御,this是動(dòng)態(tài)綁定的元镀,它可以是全局對(duì)象、當(dāng)前對(duì)象或者任意對(duì)象霎桅,這完全取決于函數(shù)的調(diào)用方式栖疑。這就導(dǎo)致了this具備了多重含義,可以使得javascript更靈活的使用滔驶。但是遇革,帶來(lái)了靈活性的同時(shí)也會(huì)給我們初學(xué)者帶來(lái)不少困惑。
全局環(huán)境中的this
console.log(this);
總結(jié):在全局作用域中它的 this 執(zhí)行當(dāng)前的全局對(duì)象(瀏覽器端是 Window揭糕,node 中是 global)
例子1:
function a(){
var user = "qintengbo";
console.log(this.user); //undefined
console.log(this); //Window
}
a();
this最終指向的是調(diào)用它的對(duì)象,這里的函數(shù)a實(shí)際是被Window對(duì)象所點(diǎn)出來(lái)的萝快,下面的代碼就可以證明。
function a(){
var user = "qintengbo";
console.log(this.user); //undefined
console.log(this); //Window
}
window.a();
和前面代碼一樣著角,其實(shí)alert也是window的一個(gè)屬性揪漩,也是window點(diǎn)出來(lái)的。
例子2:
var o = {
user:"qintengbo",
fn:function() {
console.log(this.user); ?//qintengbo
}
}
o.fn();
這里的this指向的是對(duì)象o吏口,因?yàn)槟阏{(diào)用這個(gè)fn是通過(guò)o.fn()執(zhí)行的奄容,那自然指向就是對(duì)象o冰更。
this的指向在函數(shù)定義的時(shí)候是確定不了的,只有函數(shù)執(zhí)行的時(shí)候才能確定this到底指向誰(shuí)嫩海,實(shí)際上this的最終指向的是那個(gè)調(diào)用它的對(duì)象.
其實(shí)例子1和例子2說(shuō)的并不夠準(zhǔn)確冬殃,下面這個(gè)例子就可以推翻上面的理論。
如果要徹底的搞懂this必須看接下來(lái)的幾個(gè)例子叁怪。
例子3:
var o = {
user:"qintengbo",
fn:function() {
console.log(this.user); //qintengbo
}
}
window.o.fn();
這段代碼和上面的那段代碼幾乎是一樣的审葬,但是這里的this為什么不是指向window,如果按照上面的理論奕谭,最終this指向的是調(diào)用它的對(duì)象涣觉。
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //12
}
}
}
o.b.fn();
這里同樣也是對(duì)象o點(diǎn)出來(lái)的,但是同樣this并沒(méi)有執(zhí)行它血柳,那你肯定會(huì)說(shuō)我一開(kāi)始說(shuō)的那些不就都是錯(cuò)誤的嗎官册?其實(shí)也不是,只是一開(kāi)始說(shuō)的不準(zhǔn)確难捌。
情況1:如果一個(gè)函數(shù)中有this膝宁,但是它沒(méi)有被上一級(jí)的對(duì)象所調(diào)用,那么this指向的就是window根吁,這里需要說(shuō)明的是在js的嚴(yán)格版中this指向的不是window员淫。
情況2:如果一個(gè)函數(shù)中有this,這個(gè)函數(shù)有被上一級(jí)的對(duì)象所調(diào)用击敌,那么this指向的就是上一級(jí)的對(duì)象介返。
情況3:如果一個(gè)函數(shù)中有this,這個(gè)函數(shù)中包含多個(gè)對(duì)象沃斤,盡管這個(gè)函數(shù)是被最外層的對(duì)象所調(diào)用圣蝎,this指向的也只是它上一級(jí)的對(duì)象。
證明情況3的說(shuō)法:
var o = {
a:10,
b:{
// a:12,
fn:function(){
console.log(this.a); //undefined
}
}
}
o.b.fn();
盡管對(duì)象b中沒(méi)有屬性a衡瓶,這個(gè)this指向的也是對(duì)象b徘公,因?yàn)閠his只會(huì)指向它的上一級(jí)對(duì)象,不管這個(gè)對(duì)象中有沒(méi)有this要的東西哮针。
特殊情況例子4:
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //undefined
console.log(this); //window
}
}
}
var j = o.b.fn;
j();
這里this指向的是window步淹,是不是有些蒙了?
其實(shí)是因?yàn)槟銢](méi)有理解一句話诚撵,這句話同樣至關(guān)重要:
this永遠(yuǎn)指向的是最后調(diào)用它的對(duì)象,也就是看它執(zhí)行的時(shí)候是誰(shuí)調(diào)用的键闺。
嚴(yán)格模式 ‘use strict’下的this
'use strict';
function test() {
console.log(this);
};
test();
// undefined
原因:this 并不會(huì)指向全局寿烟,而是 undefined,這樣的做法是為了消除 js 中一些不嚴(yán)謹(jǐn)?shù)男袨?/p>
jq中的this和$(this):
$("button").click(function(){
console.log(this);
console.log($(this));
});
$(this)是jquery對(duì)象辛燥,能調(diào)用jquery的方法筛武,例如click(), keyup()缝其。
而this,則是html元素對(duì)象,能調(diào)用元素屬性徘六,例如this.id,this.value内边。
例如假設(shè)已經(jīng)使得this和$(this)都指向了input對(duì)象了,若要獲得input的值,可以this.value待锈,但$(this)就得$(this).val()漠其。
var obj = {
name: 'qiutc',
foo: function() {
console.log(this);
},
foo2: function() {
console.log(this);
setTimeout(this.foo, 1000);
}
}
obj.foo2();
現(xiàn)象:兩次打印的this不一樣
可以這么這么解決:利用 閉包 的特性來(lái)處理
var obj = {
name: 'qiutc',
foo: function() {
console.log(this);
},
foo2: function() {
console.log(this);
var _this = this;
setTimeout(function() {
console.log(this); ?// Window
console.log(_this); ?// Object {name: "qiutc"}
}, 1000);
}
}
obj.foo2();
可以看到直接用 this 仍然是 Window;因?yàn)?foo2 中的 this 是指向 obj竿音,我們可以先用一個(gè)變量 _this 來(lái)儲(chǔ)存和屎,然后在回調(diào)函數(shù)中使用 _this,就可以指向當(dāng)前的這個(gè)對(duì)象了
執(zhí)行這段代碼我們會(huì)發(fā)現(xiàn)兩次打印出來(lái)的 this 是不一樣的:
第一次是 foo2 中直接打印 this春瞬,這里指向 obj 這個(gè)對(duì)象柴信,我們毋庸置疑;
但是在 setTimeout 中執(zhí)行的 this.foo 宽气,卻指向了全局對(duì)象随常,這里不是把它當(dāng)作函數(shù)的方法使用嗎?這一點(diǎn)經(jīng)常讓很多初學(xué)者疑惑萄涯;
其實(shí)绪氛,setTimeout 也只是一個(gè)函數(shù)而已,函數(shù)必然有可能需要參數(shù)窃判,我們把 this.foo 當(dāng)作一個(gè)參數(shù)傳給 setTimeout 這個(gè)函數(shù)钞楼,就像它需要一個(gè) fun 參數(shù),在傳入?yún)?shù)的時(shí)候袄琳,其實(shí)做了個(gè)這樣的操作 fun = this.foo询件,看到?jīng)]有,這里我們直接把 fun 指向 this.foo 的引用唆樊;執(zhí)行的時(shí)候其實(shí)是執(zhí)行了 fun() 所以已經(jīng)和 obj 無(wú)關(guān)了宛琅,它是被當(dāng)作普通函數(shù)直接調(diào)用的,因此 this 指向全局對(duì)象逗旁。
這個(gè)問(wèn)題是很多異步回調(diào)函數(shù)中普遍會(huì)碰到的嘿辟;
百度14年的筆試題:
var myObject = {
foo:"bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
(function (){
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
}());
}
}
myObject.func();
這里分別會(huì)打印出什么?
問(wèn)題:當(dāng)this遇到return時(shí)會(huì)發(fā)生什么片效?
如果返回值是一個(gè)對(duì)象红伦,那么this指向的就是那個(gè)返回的對(duì)象,如果返回值不是一個(gè)對(duì)象那么this還是指向函數(shù)的實(shí)例淀衣。