this是JS中的關(guān)鍵字,this的指向中函數(shù)定義時(shí)確定不了,只有 函數(shù)指向的時(shí)候才能確定this到底指向誰(shuí),this的最終指向的是那個(gè)調(diào)用他的對(duì)象
牢記以下三點(diǎn)
- this指向的,只可能是對(duì)象!
2.this指向誰(shuí),不取決于this寫(xiě)在哪!而是取決于函數(shù)在哪里進(jìn)行調(diào)用。
3.this指向的對(duì)象,稱之為函數(shù)的上下文context,也叫函數(shù)的調(diào)用者。
下面我用幾個(gè)例子解釋一下this
例子1:
function fn(){
var aa= "88";
console.log(this.aa); //undefined
console.log(this); //Window
}
fn();
我們上面說(shuō)this只有在函數(shù)執(zhí)行的時(shí)候,才能去判斷它最終指向的調(diào)用它的對(duì)象,函數(shù)是由window對(duì)象調(diào)用的,所以自然指向window,然而在window的屬性中,沒(méi)有aa這個(gè)變量,所以結(jié)果為undefined
function fn(){
var aa= "88";
console.log(this.aa); //undefined
console.log(this); //Window
}
window.fn();//window可以省略 等同于上面的代碼
例子2:
var obj = {
name:"張三",
who:function(){
console.log(this.name); //張三
}
}
obj.who();
函數(shù)在對(duì)象obj里面,調(diào)用函數(shù)時(shí),是通過(guò)obj.who()調(diào)用的,所以這里的this指向obj,而obj里面是有一個(gè)name屬性值的,所以結(jié)果為張三。
結(jié)合這兩個(gè)例子,我們應(yīng)該了解了this指向調(diào)用它的對(duì)象,但是對(duì)this的了解還不夠深入,下面我再寫(xiě)幾個(gè)例子補(bǔ)充一下
例子3:
var name ="李二" ;
var person = {
name:"李三",
say:function(){
console.log(this.name); //李三
}
}
window.person.say();
從這個(gè)例子可以看出,如果按照上面的推論的話,這里的this最終應(yīng)該指向window,結(jié)果為李二才對(duì)。接著看下面這個(gè)例子
var obj= {
a:10,
b:{ a:12,
fn:function(){
console.log(this.a);//12
}
}
}
obj.b.fn();
如果根據(jù)上面的推斷的話,這里的this應(yīng)該指向obj才對(duì),this.a結(jié)果應(yīng)該為10才對(duì)。這樣看來(lái),可能你會(huì)覺(jué)得開(kāi)頭對(duì)于this指向的認(rèn)知是錯(cuò)誤的。其實(shí)并不是,只是不夠準(zhǔn)確而已。以下三條補(bǔ)充
如果一個(gè)函數(shù)中有this,但是它沒(méi)有被上一級(jí)的對(duì)象所調(diào)用,那么this指向的就是window。
如果一個(gè)函數(shù)中有this,這個(gè)函數(shù)有被上一級(jí)的對(duì)象所調(diào)用,那么this指向的就是上一級(jí)的對(duì)象。
如果一個(gè)函數(shù)中有this,這個(gè)函數(shù)中被多個(gè)對(duì)象包含,盡管這個(gè)函數(shù)是被最外層的對(duì)象所調(diào)用,this指向的也只是它上一級(jí)的對(duì)象
下面再看幾個(gè)例子
例子4:
var obj = {
a: 1,
b: {
fn: function() {
console.log(this.a) // undefined
}
}
}
obj.b.fn()
輸入的值是undefined,也就是說(shuō),這個(gè)時(shí)候this指向的是b的作用域,而b中沒(méi)有定義a,所以是undefined
var obj = {
a: 1,
b: {
a: 2,
fn: function() {
console.log(this) // Window
console.log(this.a) // undefined
}
}
}
var x = obj.b.fn
x()
誰(shuí)調(diào)用,指向誰(shuí),這一句var x = obj.b.fn只是進(jìn)行了賦值,把 fn賦值給了全局變量 x ,然而最終的調(diào)用時(shí)機(jī)是在 window作用域調(diào)用的函數(shù) x(), 所以 this的指向是window對(duì)象
那我們?nèi)绾胃淖?this 的指向呢?
通過(guò) call, apply, bind 改變 this 的指向
例子5:
var name = "小貓";
var food = "魚(yú)"
var obj = {
name:this.name,
food:this.food,
state: function(name, food){
console.log(`${this.name} 最喜歡的食物是${this.food}`)
}
}
var skills = {
name: '狗',
food: "骨頭",
}
obj.state() //小貓 最喜歡的食物是魚(yú)
obj.state.call(skills)//狗 最喜歡的食物是骨頭
obj.state.apply(skills) //狗 最喜歡的食物是骨頭
obj.state.bind(skills)()//狗 最喜歡的食物是骨頭
從上面看出來(lái), call, apply, bind把this的指向改變?yōu)閏all, apply, bind所傳入的第一個(gè)參數(shù), 除此之外,他們是沒(méi)有什么區(qū)別的,看看下面的例子
var name= "兔子"
var food = "胡蘿卜"
var obj = {
food:this.food,
name:this.name,
state: function(name, ow){
console.log(`${this.name} 愛(ài)吃 ${this.food},但是${name}愛(ài)吃${ow}`)
}
}
var skills = {
name: "熊二" ,
food: '蜂蜜'
}
obj.state("羊","草") //兔子 愛(ài)吃 胡蘿卜,但是羊愛(ài)吃草
obj.state.call(skills,"大灰狼","小綿羊") //熊二 愛(ài)吃 蜂蜜,但是大灰狼愛(ài)吃小綿羊
obj.state.apply(skills,["狐貍","葡萄"]) // 熊二 愛(ài)吃 蜂蜜,但是狐貍愛(ài)吃葡萄
obj.state.bind(skills,"貓","魚(yú)")() //熊二 愛(ài)吃 蜂蜜,但是貓愛(ài)吃魚(yú)
apply第二個(gè)參數(shù)接受的是一個(gè)數(shù)組, call 直接按參數(shù)排列就可以了,而 bind 跟call相似,只不過(guò)后面多了個(gè) ()
上面是本人對(duì)于this指向的一些理解,如有錯(cuò)誤或不足,望指出。