前言
this在不同的使用情景中,含義多變蝴悉,看著看著就可能蒙圈彰阴。后面發(fā)現(xiàn)通過(guò)實(shí)例的方式來(lái)學(xué)習(xí)this,通過(guò)審查元素直接查看this指向的結(jié)果拍冠,對(duì)this會(huì)清晰很多尿这。
總的而言,this指向全局對(duì)象window的情況有:全局直接調(diào)用this庆杜、在函數(shù)中調(diào)用this和setTimeout和setInterval方法的this射众。而dom對(duì)象綁定事件中的this、構(gòu)造函數(shù)中的this晃财、對(duì)象方法中的this則各有所指叨橱,不再指向全局對(duì)象window。具體見(jiàn)例子說(shuō)明断盛。
一雏逾、this為全局對(duì)象
直接調(diào)用時(shí)指向全局對(duì)象。在瀏覽器里郑临,全局對(duì)象就是window
<script>
console.log(this)
</script>
結(jié)果輸出為:window對(duì)象
再舉一個(gè)栗子:
window.name = 'aaa';
function getName(){
console.log(this.name);
}
getName(); // aaa
二栖博、this在函數(shù)中調(diào)用
在函數(shù)中直接調(diào)用this,this也是指向全局對(duì)象window厢洞。所以在下面這個(gè)例子中仇让,this.b是指向全局變量b=2,而非函數(shù)里的局部變量b=100
<script>
var a=1
var b=2
function testthis() {
var b=100
console.log(this) //輸出結(jié)果為:window
console.log(this.a) //輸出結(jié)果為:1
console.log(this.b) //輸出結(jié)果為:2
}
testthis()
</script>
在函數(shù)內(nèi)部的嵌套函數(shù)中的this典奉,也是指向全局對(duì)象window,而非其父函數(shù)丧叽。
<script>
var a=1
var b=2
function test(){
function innertest(){
console.log(this) //輸出結(jié)果為:window
console.log(this.b) //輸出結(jié)果為:2
}
innertest()
}
test()
</script>
三卫玖、dom對(duì)象綁定事件中的this
dom對(duì)象綁定事件中的this,指向的是dom對(duì)象踊淳。這種情形的使用很常見(jiàn)假瞬。
<body>
<button class="domtest">dianwo</button>
<script>
var $domtest=document.querySelector('.domtest')
$domtest.addEventListener('click',function(){
console.log(this)
console.log($(this))
})
</script>
</body>
輸出結(jié)果如下:
this指向<button class="domtest">dianwo</button>
對(duì)象.
$(this)則是指向button元素做了一層包裹后的jquery對(duì)象。
四迂尝、特例:setTimeout和setInterval方法
setTimeout和setInterval方法中的this脱茉,就指向全局對(duì)象window。即使setTimeout或setInterval方法用在dom對(duì)象的綁定事件下垄开,也是指向全局對(duì)象window琴许。
那如果在這情景中,我就是想要在setTimeout方法中溉躲,讓this能指向dom對(duì)象呢榜田?
在這個(gè)例子,就使用了賦值借位的方式var _this=this
锻梳,也是實(shí)際應(yīng)用中常見(jiàn)的做法箭券。
var _this=this
處于$domtest.addEventListener
事件下的第一層級(jí),this就指向$domtest對(duì)象疑枯,即<button class="domtest">dianwo</button>
元素辩块,將其賦值給_this。然后在setTimeout方法中使用_this神汹,就也能指向$domtest對(duì)象庆捺。
<body>
<button class="domtest">dianwo</button>
<script>
var $domtest=document.querySelector('.domtest')
$domtest.addEventListener('click',function(){
console.log(this) //輸出結(jié)果為:<button class="domtest">dianwo</button>
var _this=this
setTimeout(function(){
console.log(_this) //輸出結(jié)果為:<button class="domtest">dianwo</button>
console.log(this) //輸出結(jié)果為:window
},300)
})
</script>
</body>
五、構(gòu)造函數(shù)中的this
構(gòu)造函數(shù)就是通過(guò)這個(gè)函數(shù)來(lái)實(shí)例化生成一個(gè)對(duì)象屁魏。那么構(gòu)造函數(shù)中的this滔以,就是指這個(gè)構(gòu)造函數(shù)實(shí)例化之后的對(duì)象。
<script>
function exp(name){
this.name=name
}
exp.prototype.print=function(){
console.log(this.name)
}
exp.prototype.run="running"
var p1=new exp('hyh') //實(shí)例化為對(duì)象p1氓拼,這時(shí)p1的屬性name等于它的參數(shù)‘hyh’
p1.print() //輸出p1的屬性name
console.log(p1.run) //輸出通過(guò)原型定義的屬性run
var p2=new exp('hyha') //實(shí)例化為對(duì)象p2你画,這時(shí)p1的屬性name等于它的參數(shù)‘hyha’
p2.print() //輸出p2的屬性name
console.log(p2.run) ////輸出通過(guò)原型定義的屬性run
</script>
輸出結(jié)果為:
如果,在構(gòu)造函數(shù)中return返回一個(gè)同名變量桃漾,那么 this 則會(huì)指向該變量坏匪。
<script>
var Person = function(){
this.name = 'hahaha';
this.sex= 'female';
return {
name:'aaa'
}
}
var obj = new Person();
console.log(obj.name); //aaa
console.log(obj.sex); //undefined
</script>
六、對(duì)象方法中的this
函數(shù)是一種特殊的對(duì)象撬统,在對(duì)象中可以直接作為對(duì)象的屬性适滓,也就直接看做是對(duì)象的方法。在作為對(duì)象方法的這個(gè)函數(shù)中恋追,調(diào)用this就指向這個(gè)對(duì)象凭迹。
<script>
var obj1={
name:'byron',
fn:function(){
console.log(this);
},
fn2:function(){
console.log(this.name);
},
};
obj1.fn();
obj1.fn2();
</script>
輸出結(jié)果罚屋,this為這個(gè)obj1對(duì)象,this.name就自然指向obj1對(duì)象的name屬性:
對(duì)這個(gè)例子嗅绸,還可再引申一個(gè)例子脾猛,因?yàn)榫哂谢煜裕T诿嬖囶}中可見(jiàn):
<body>
<script>
var obj1={
name:'byron',
fn:function(){
console.log(this);
}
};
obj1.fn();
var fn2=obj1.fn;
//等同于fn2=function(){console.log(this);}
fn2() //window
</script>
</body>
這個(gè)例子的輸出結(jié)果為:fn2()等于window對(duì)象鱼鸠。
面對(duì)這種題猛拴,最重要還是分清楚層級(jí)。fn2對(duì)象和obj1是同一層級(jí)的對(duì)象蚀狰,彼此獨(dú)立愉昆,沒(méi)有關(guān)系了。兩者都是script標(biāo)簽下直接第一層的對(duì)象造锅。var fn2=obj1.fn等同于fn2=function(){console.log(this);}
撼唾,所以fn2是函數(shù)對(duì)象廉邑,執(zhí)行生效的寫(xiě)法為fn2()哥蔚。這就變成在函數(shù)中調(diào)用this的情況了,這里的this就指向全局window蛛蒙,此時(shí)就輸出window糙箍。
七、對(duì)象中的對(duì)象方法的this
如果一個(gè)對(duì)象作為另一個(gè)對(duì)象的屬性牵祟,對(duì)象嵌套對(duì)象深夯,那么這個(gè)對(duì)象中的this是指向誰(shuí)呢?我們看下例子:
<script>
var obj2={
name:'byron',
obj3:{
run:'aaa',
fn:function(){
console.log(this);
}
}
};
obj2.obj3.fn();
</script>
輸出結(jié)果為:this所在的這個(gè)對(duì)象
八诺苹、對(duì)象中直接的this
上面第六和第七兩個(gè)例子的this是對(duì)象的函數(shù)方法中的this咕晋,那如果我想直接將this指定給對(duì)象屬性fn,而不是寫(xiě)到函數(shù)中收奔,那this會(huì)指向什么呢掌呜?改寫(xiě)下例子如下,此時(shí)的this結(jié)果是指向window對(duì)象
<script>
var obj1={
name:'byron',
fn:console.log(this)
};
obj1.fn;
</script>
輸出結(jié)果:
obj1.fn等同于console.log(this)
坪哄,那就是等同于開(kāi)頭第一個(gè)例子的情形质蕉,直接調(diào)用this,等同于全局對(duì)象window翩肌。
九模暗、一次性將變量說(shuō)清楚
變量類型,可以歸總為:
- 實(shí)例變量:也就是this.xxx念祭,只有類實(shí)例化之后的對(duì)象才能訪問(wèn)到的變量
- 靜態(tài)變量:也就是屬性兑宇,它所屬對(duì)象能訪問(wèn)到的變量
- 局部變量:當(dāng)前作用域內(nèi)有效的變量
下面的例子,對(duì)這三種變量都有體現(xiàn)粱坤,其輸出的結(jié)果也讓我對(duì)這三個(gè)變量加深理解:
<body>
<script>
function exp(){
var a=1; //局部變量
this.b=2; //實(shí)例變量
console.log(a)
}
exp.c=3; //c為exp這個(gè)函數(shù)的屬性隶糕,函數(shù)是特殊對(duì)象祝钢,也可以有屬性
console.log(exp.c); //3
var obj=new exp(); //1
console.log(a); //error
console.log(obj.a); //undefined
console.log(obj.b); //2
console.log(obj.c); //undefined
</script>
</body>
a是exp函數(shù)的局部變量,只有在exp函數(shù)中才生效若厚。所以如果直接在外面console.log(a)
拦英,就會(huì)因?yàn)檎也坏絘而報(bào)錯(cuò)。
將exp函數(shù)實(shí)例化為obj對(duì)象测秸,this.b說(shuō)明b可以被實(shí)例化后的obj對(duì)象直接訪問(wèn)使用疤估,因此console.log(obj.b)
的結(jié)果為2。而此時(shí)注意霎冯,因?yàn)閍是局部變量铃拇,不同于b,obj對(duì)象直接訪問(wèn)調(diào)用沈撞,是無(wú)效的慷荔,所以 console.log(obj.a)
的結(jié)果是undefined。
a這個(gè)局部變量生效的體現(xiàn)就是缠俺,實(shí)例化obj時(shí)显晶,就會(huì)逐行執(zhí)行exp函數(shù),此時(shí)a作為函數(shù)中的局部變量壹士,console.log(a)
生效磷雇,輸出1
屬性c為exp這個(gè)函數(shù)的屬性,函數(shù)是特殊對(duì)象躏救,也可以有屬性唯笙。因此console.log(exp.c)
等于3,而實(shí)例化的對(duì)象obj是沒(méi)有這個(gè)屬性的盒使,所以 console.log(obj.c)
的結(jié)果為undefined崩掘。
需要記住的一點(diǎn)就是,this.xxx的變量只有實(shí)例化的對(duì)象才能訪問(wèn)少办。實(shí)例化的對(duì)象也只能訪問(wèn)this.xxx的xxx變量苞慢。
十、結(jié)語(yǔ)
除了上面列舉的this的使用情景之外凡泣,call枉疼,apply和bind也和this的使用緊密相連的。和上面介紹的setTimeout方法例子中使用var _this=this的借位思想一樣鞋拟,call骂维,apply和bind的使用能夠改變this的指向?qū)ο蟆?duì)call贺纲,apply和bind方法航闺,看我寫(xiě)的下一篇:栗子最實(shí)在:用實(shí)例來(lái)說(shuō)明call、apply和bind方法。