JS this 指向

JS 里的 this

  • 1、在 function 內(nèi)部被創(chuàng)建
  • 2、指向調(diào)用時(shí)所在函數(shù)所綁定的對(duì)象
  • 3渔彰、this 不能被賦值,但可以被 call/apply/bind 改變
this 的指向在函數(shù)定義的時(shí)候是確定不了的推正,只有函數(shù)執(zhí)行的時(shí)候才能確定 this 到底指向誰(shuí)恍涂,實(shí)際上 this 的最終指向的是最近調(diào)用該 this 所在的函數(shù)的對(duì)象( this 所在的函數(shù)由哪個(gè)最近的對(duì)象調(diào)用,this 就會(huì)指向誰(shuí))舔稀,當(dāng)函數(shù)執(zhí)行時(shí)乳丰,沒(méi)有明確的調(diào)用對(duì)象時(shí),則 this 指向 window
例子1:
function a(){
    var user = "簡(jiǎn)書(shū)";
    console.log(this); // this --> Window
    console.log(this.user); // undefined
}
a();

`按照我們上面說(shuō)的 this 最終指向的是最近調(diào)用該函數(shù)的對(duì)象内贮,這里的函數(shù) a 實(shí)際是被 Window 對(duì)象所點(diǎn)出來(lái)的产园,下面的代碼就可以證明`

function a(){
    var user = "簡(jiǎn)書(shū)";
    console.log(this); // this --> Window
    console.log(this.user); // undefined
}
window.a();
例子2:
var o = {
    user: "簡(jiǎn)書(shū)",
    fn: function(){
        console.log(this); // this --> o
        console.log(this.user);  // 簡(jiǎn)書(shū)
    }
}
o.fn();

`這里的 this 指向的是對(duì)象 o,因?yàn)槟阏{(diào)用這個(gè) fn 是通過(guò) o.fn() 執(zhí)行的夜郁,那自然指向就是對(duì)象 o什燕,
這里再次強(qiáng)調(diào)一點(diǎn),this 的指向在函數(shù)創(chuàng)建的時(shí)候是決定不了的竞端,在調(diào)用的時(shí)候才能決定屎即,誰(shuí)調(diào)用的就指向誰(shuí),一定要搞清楚這個(gè)`

var o = {
    user: "簡(jiǎn)書(shū)",
    fn: function(){
        console.log(this); // this --> o
        console.log(this.user); // 簡(jiǎn)書(shū)
    }
}
window.o.fn();

`這段代碼和上面的那段代碼幾乎是一樣的事富,但是這里的 this 為什么不是指向 window技俐,如果按照上面的理論,最終 this 指向的是調(diào)用該函數(shù)的對(duì)象统台,
這里先說(shuō)個(gè)題外話雕擂,window 是 js 中的全局對(duì)象,我們創(chuàng)建的變量實(shí)際上是給 window 添加屬性贱勃,所以這里可以用 window 點(diǎn) o 對(duì)象`

這里先不解釋為什么上面的那段代碼 this 為什么沒(méi)有指向 window井赌,我們?cè)賮?lái)看一段代碼

例子3:
var o = {
    a: 10,
    b: {
        a: 12,
        fn: function(){
            console.log(this); // this --> b
            console.log(this.a); // 12
        }
    }
}
o.b.fn()

`這里同樣也是對(duì)象 o 點(diǎn)出來(lái)的谤逼,但是同樣 this 并沒(méi)有指向它,那你肯定會(huì)說(shuō)我一開(kāi)始說(shuō)的那些不就都是錯(cuò)誤的嗎仇穗?
其實(shí)也不是流部,只是一開(kāi)始說(shuō)的不準(zhǔn)確,接下來(lái)我將補(bǔ)充一句話纹坐,我相信你就可以徹底的理解 this 的指向的問(wèn)題`
情況1:如果一個(gè)函數(shù)中有 this枝冀,但是它沒(méi)有被上一級(jí)的對(duì)象所調(diào)用,那么 this 指向的就是 window恰画,這里需要說(shuō)明的是在 js 的嚴(yán)格版中 this 指向的不是 window宾茂,但是我們這里不探討嚴(yán)格版的問(wèn)題,你想了解可以自行上網(wǎng)查找
情況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可以證明费封,如果不相信焕妙,那么接下來(lái)看例子4
例子4:
var o = {
    a: 10,
    b: {
        // a: 12,
        fn: function(){
            console.log(this); // this --> b
            console.log(this.a); // undefined
        }
    }
}
o.b.fn()

`盡管對(duì)象 b 中沒(méi)有屬性 a壁肋,這個(gè) this 指向的也是對(duì)象 b越败,因?yàn)?this 只會(huì)指向它的上一級(jí)對(duì)象,不管這個(gè)對(duì)象中有沒(méi)有 this 要的東西`
例子5:
var o = {
    a: 10,
    b: {
        a: 12,
        fn: function(){
            console.log(this); // this --> window
            console.log(this.a); // undefined
        }
    }
}
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)用的锤窑,例子5中雖然函數(shù) fn 是被對(duì)象 b 所引用璧针,但是在將 fn 賦值給變量 j 的時(shí)候并沒(méi)有執(zhí)行,所以最終指向的是 window渊啰,這和例子4是不一樣的探橱,例子4是直接執(zhí)行了 fn

this 講來(lái)講去其實(shí)就是那么一回事,只不過(guò)在不同的情況下指向的會(huì)有些不同绘证,上面的總結(jié)每個(gè)地方都有些小錯(cuò)誤隧膏,也不能說(shuō)是錯(cuò)誤,而是在不同環(huán)境下情況就會(huì)有不同嚷那,所以我也沒(méi)有辦法一次解釋清楚胞枕,只能你慢慢地的去體會(huì)

再舉一個(gè)常見(jiàn)的例子,關(guān)于事件綁定
例子6:
btn.onclick = function(){
    console.log(this); // this --> btn
}
btn.onclick();
function fn(){
    console.log(this); // this --> obj
}

var obj = {
    show: fn
}

btn.onclick = function(){
    window.setTimeout(function(){
        obj.show();
    }, 100);
}

`自行體會(huì)一下车酣,為什么這個(gè) this 指向的是 obj`

科學(xué)是嚴(yán)謹(jǐn)?shù)那冢贸鼋Y(jié)論之前,我們還是要反復(fù)驗(yàn)證湖员,再看一個(gè)例子

例子7:
btn.onclick = function(){
    setTimeout(function(){
        console.log(this); // this --> Window
    }, 0);
}
btn.onclick();

`當(dāng)函數(shù)執(zhí)行時(shí)贫悄,沒(méi)有明確的調(diào)用對(duì)象時(shí),則 this 指向 Window`

從例子7代碼中看的出來(lái)娘摔, this 不再函數(shù) btn 的內(nèi)部窄坦,而是在函數(shù) setTimeout 的內(nèi)部,所以結(jié)果沒(méi)有打印出 btn凳寺, 現(xiàn)在我們也不感到奇怪了
你可能還要問(wèn)鸭津,為什么函數(shù) setTimeout 里的 this 指向 window 呢?
這里其實(shí)算是一個(gè)特例肠缨,傳入定時(shí)器的函數(shù)逆趋,是由哪個(gè)對(duì)象調(diào)用的?我們不得而知晒奕,這種情況闻书,this 就指向 window,以下例子8脑慧、例子9同樣

例子8:
function m1(){
    function m2(){
        console.log(this); // this --> Window
    }
    m2();
}
m1();
例子9:
var name = "the window";
var object = {
    name: "my object",
    getNameFunc: function(){
        return function(){
            return this.name; // this --> Window
        }
    }
}
console.log(object.getNameFunc()()); // the window
由 this 衍生出的問(wèn)題

剛才遺留了一個(gè)問(wèn)題沒(méi)有解決

btn.onclick = function(){
    setTimeout(function(){
        console.log(this); // this --> Window
    }, 0);
}
btn.onclick();

我們期待 this 指向 btn魄眉,而 this 現(xiàn)在卻指向了 window,這個(gè)問(wèn)題該怎么修復(fù)呢闷袒? 有很多辦法
如果你不知道call坑律、apply、bind囊骤,那么恐怕你只能看得懂例子10的方法

例子10:
var name = "the window";
var object = {
    name: "my object",
    getNameFunc: function(){
        var that = this;
        return function(){
            return that.name; // that --> object
        }
    }
}
console.log(object.getNameFunc()()); // my object




btn.onclick = function(){
    var that = this; // 使用變量保存 this晃择,that 變量的值是不會(huì)隨著環(huán)境改變的
    setTimeout(function(){
        console.log(that); // that --> btn
    },0);
}
btn.onclick();
例子11:
btn.onclick = function(){
    var that = this; // 使用變量保存 this
 
    function fn(){  // 將代碼寫(xiě)在一個(gè)函數(shù) fn 中
        console.log(this); // this --> btn
    }

    setTimeout(function(){
        fn.call(that); // 強(qiáng)行指定 this 為 that 對(duì)象
    }, 0);
}
btn.onclick();

/*
  call 方法的作用,是調(diào)用函數(shù)淘捡,同時(shí)指定 this 可以代表誰(shuí)
  例如 fn.call(obj)
  意思就是 調(diào)用函數(shù) fn藕各,并且 this 指向 obj 對(duì)象
*/
例子12:
btn.onclick = function(){
    var that = this; // 使用變量保存 this
 
    function fn(){  // 將代碼寫(xiě)在一個(gè)函數(shù) fn 中
        console.log(this); // this --> btn
    }

    setTimeout(function(){
        fn.apply(that); // 使用 apply 方法調(diào)用函數(shù),強(qiáng)行指定 this 為 that 對(duì)象
    }, 0);
}
btn.onclick();

/*
  apply 方法的作用焦除,是調(diào)用函數(shù)激况,同時(shí)指定 this 可以代表誰(shuí)
  例如 fn.apply(obj)
  意思就是 調(diào)用函數(shù) fn,并且 this 指向 obj 對(duì)象
*/
例子13:
btn.onclick = function(){
    setTimeout(function(){
        console.log(this); // this --> btn
    }.bind(this), 0);
    // 使用 bind 方法膘魄,將定時(shí)器函數(shù)的 this 強(qiáng)行綁定為事件函數(shù)的 this
}
btn.onclick();

/*
  bind 方法的作用乌逐,是綁定函數(shù)的 this,同時(shí)返回綁定后的新函數(shù)
  例如 
  var fb = fn.bind(obj);
  window.fb();
  無(wú)論誰(shuí)調(diào)用 fb 函數(shù), 函數(shù)的 this 都會(huì)指向 obj
*/
關(guān)于自行改變 this 的指向請(qǐng)看JavaScript中call, apply, bind方法的總結(jié)创葡,詳細(xì)的說(shuō)明了我們?nèi)绾问謩?dòng)更改 this 的指向

箭頭函數(shù)版 this

1.如何判斷箭頭函數(shù)的 this

因?yàn)榧^函數(shù)不具備自己的 this浙踢,所以非常簡(jiǎn)單,假裝它不存在灿渴,就像這樣


箭頭函數(shù)版this.jpg

這下 this 的指向非常清晰了吧

2. 箭頭函數(shù)可以用 call 來(lái)改變 this 指向嗎洛波?

不能R扔摺! 試圖改變箭頭函數(shù)的 this 是徒勞的


call改變箭頭函數(shù)的this.jpg

構(gòu)造函數(shù)版 this

function Fn(){
    this.user = "簡(jiǎn)書(shū)";
}
var a = new Fn();
console.log(a.user); // 簡(jiǎn)書(shū)

這里之所以對(duì)象 a 可以點(diǎn)出函數(shù) Fn 里面的 user 是因?yàn)?new 關(guān)鍵字可以改變 this 的指向蹬挤,將這個(gè) this 指向?qū)ο?a缚窿,為什么我說(shuō) a 是對(duì)象,因?yàn)橛昧?new 關(guān)鍵字就是創(chuàng)建一個(gè)對(duì)象實(shí)例焰扳,我們這里用變量 a 創(chuàng)建了一個(gè) Fn 的實(shí)例(相當(dāng)于復(fù)制了一份 Fn 到對(duì)象 a 里面)倦零,此時(shí)僅僅只是創(chuàng)建,并沒(méi)有執(zhí)行吨悍,而調(diào)用這個(gè)函數(shù) Fn 的是對(duì)象 a扫茅,那么 this 指向的自然是對(duì)象 a,那么為什么對(duì)象 a 中會(huì)有 user育瓜,因?yàn)槟阋呀?jīng)復(fù)制了一份 Fn 函數(shù)到對(duì)象 a 中葫隙,用了 new 關(guān)鍵字就等同于復(fù)制了一份

更新一個(gè)小問(wèn)題當(dāng) this 碰到 return 時(shí)
function fn()  {  
    this.user = '簡(jiǎn)書(shū)';  
    return {};  
}
var a = new fn;  
console.log(a.user); // undefined
function fn()  {  
    this.user = '簡(jiǎn)書(shū)';  
    return function(){};
}
var a = new fn;  
console.log(a.user); // undefined
function fn()  {  
    this.user = '簡(jiǎn)書(shū)';  
    return 1;
}
var a = new fn;  
console.log(a.user); // 簡(jiǎn)書(shū)
function fn()  {  
    this.user = '簡(jiǎn)書(shū)';  
    return undefined;
}
var a = new fn;  
console.log(a.user); // 簡(jiǎn)書(shū)

如果返回值是一個(gè)對(duì)象,那么 this 指向的就是那個(gè)返回的對(duì)象躏仇,如果返回值不是一個(gè)對(duì)象那么 this 還是指向函數(shù)的實(shí)例

function fn()  {  
    this.user = '簡(jiǎn)書(shū)';  
    return undefined;
}
var a = new fn;  
console.log(a); // fn {user: "簡(jiǎn)書(shū)"}

還有一點(diǎn)就是雖然 null 也是對(duì)象停蕉,但是在這里 this 還是指向那個(gè)函數(shù)的實(shí)例,因?yàn)?null 比較特殊

function fn()  {  
    this.user = '簡(jiǎn)書(shū)';  
    return null;
}
var a = new fn;  
console.log(a.user); // 簡(jiǎn)書(shū)

知識(shí)點(diǎn)補(bǔ)充:
1.在嚴(yán)格版中的默認(rèn)的 this 不再是 window钙态,而是 undefined慧起。
2.new 操作符會(huì)改變函數(shù) this 的指向問(wèn)題,雖然我們上面講解過(guò)了册倒,但是并沒(méi)有深入的討論這個(gè)問(wèn)題蚓挤,網(wǎng)上也很少說(shuō),所以在這里有必要說(shuō)一下

function fn(){
   this.num = 1;
}
var a = new fn();
console.log(a.num); // 1

為什么 this 會(huì)指向 a驻子?首先 new 關(guān)鍵字會(huì)創(chuàng)建一個(gè)空的對(duì)象灿意,然后會(huì)自動(dòng)調(diào)用一個(gè)函數(shù) apply 方法,將 this 指向這個(gè)空對(duì)象崇呵,這樣的話函數(shù)內(nèi)部的 this 就會(huì)被這個(gè)空的對(duì)象替代

通過(guò) call() 和 apply() 改變函數(shù)執(zhí)行環(huán)境的情況下缤剧,this 就會(huì)指向其他對(duì)象

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市域慷,隨后出現(xiàn)的幾起案子荒辕,更是在濱河造成了極大的恐慌,老刑警劉巖犹褒,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抵窒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡叠骑,警方通過(guò)查閱死者的電腦和手機(jī)李皇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)宙枷,“玉大人掉房,你說(shuō)我怎么就攤上這事茧跋。” “怎么了卓囚?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵厌衔,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我捍岳,道長(zhǎng),這世上最難降的妖魔是什么睬隶? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任锣夹,我火速辦了婚禮,結(jié)果婚禮上苏潜,老公的妹妹穿的比我還像新娘银萍。我一直安慰自己,他們只是感情好恤左,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布贴唇。 她就那樣靜靜地躺著,像睡著了一般飞袋。 火紅的嫁衣襯著肌膚如雪戳气。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,590評(píng)論 1 305
  • 那天巧鸭,我揣著相機(jī)與錄音瓶您,去河邊找鬼。 笑死纲仍,一個(gè)胖子當(dāng)著我的面吹牛呀袱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播郑叠,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼夜赵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了乡革?” 一聲冷哼從身側(cè)響起寇僧,我...
    開(kāi)封第一講書(shū)人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沸版,沒(méi)想到半個(gè)月后婉宰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡推穷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年心包,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片馒铃。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蟹腾,死狀恐怖痕惋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情娃殖,我是刑警寧澤值戳,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站炉爆,受9級(jí)特大地震影響堕虹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芬首,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一赴捞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧郁稍,春花似錦赦政、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至财破,卻和暖如春掰派,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背左痢。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工碗淌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抖锥。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓亿眠,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親磅废。 傳聞我的和親對(duì)象是個(gè)殘疾皇子纳像,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 最近有點(diǎn)閑暇時(shí)間,就來(lái)總結(jié)js中this的指向問(wèn)題拯勉,如有不對(duì)竟趾,請(qǐng)指出。this指向宫峦,網(wǎng)上做多的描述是指向那個(gè)最終調(diào)...
    AlisaMfz閱讀 566評(píng)論 0 0
  • 1.背景介紹 在javaScript中导绷,this是動(dòng)態(tài)綁定的犀勒,它可以是全局對(duì)象、當(dāng)前對(duì)象或者任意對(duì)象,這完全取決于...
    yaolei72閱讀 338評(píng)論 0 0
  • 首先必須要說(shuō)的是贾费,this的指向在函數(shù)定義的時(shí)候是確定不了的钦购,只有函數(shù)執(zhí)行的時(shí)候才能確定this到底指向誰(shuí),實(shí)際上...
    Mr__王閱讀 731評(píng)論 0 3
  • 首先必須要說(shuō)的是唱凯,this的指向在函數(shù)定義的時(shí)候是確定不了的,只有函數(shù)執(zhí)行的時(shí)候才能確定this到底指向誰(shuí)谎痢,實(shí)際上...
    sunnyghx閱讀 208評(píng)論 1 0
  • 首先必須要說(shuō)的是磕昼,this的指向在函數(shù)定義的時(shí)候是確定不了的,只有函數(shù)執(zhí)行的時(shí)候才能確定this到底指向誰(shuí)舶得,實(shí)際上...
    web蝸牛閱讀 582評(píng)論 1 4