RN this指針

解決問題:如何準確判斷this指向的是什么
this是什么?

首先記住this不是指向自身!this就是一個指針,指向調(diào)用函數(shù)的對象?!緞澲攸c:調(diào)用函數(shù)的對象、對象、對象?。。?/strong>】

首先需要知道this的綁定規(guī)則
1、默認綁定

默認綁定 在不能應(yīng)用其它綁定規(guī)則時使用的默認規(guī)則,通常是獨立函數(shù)調(diào)用。

function sayHi() {
    console.log('Hello,',this.name);
}

var name = 'ZSZ'

sayHi();

在調(diào)用sayHi()時,應(yīng)用了默認綁定,this指向全局對象(非嚴格模式下),嚴格模式下,this指向undefined,undefined上沒有this對象,會拋出錯誤。

上面的代碼,如果在瀏覽器環(huán)境中運行,那么結(jié)果就是 Hello,ZSZ

但是如果在node環(huán)境中運行,結(jié)果就是Hello,undefined.這是因為node中name并不是掛在全局對象上的。

2、隱式綁定

隱式綁定函數(shù)的調(diào)用是在某個對象上觸發(fā)的,即調(diào)用位置上存在上下文對象。典型的形式為 XXX.fun().

function sayHi() {
    console.log('Hello,',this.name);
}

var person = {
    name:'ZSZ01',
    sayHi:sayHi
}

var name = 'ZSZ02';

person.sayHi();

打印的結(jié)果是Hello,ZSZ01.
sayHi函數(shù)聲明在外部,嚴格來說并不屬于person,但是在調(diào)用sayHi時,調(diào)用位置會使用person上下文來引用函數(shù),隱式綁定會把函數(shù)調(diào)用中的this(即此例sayHi函數(shù)中的this)綁定到這個上下文對象(即此例中的person)
需要注意的是:對象屬性鏈中只有最后一層會影響到調(diào)用位置。例子如下:

function sayHi() {
    console.log('Hello,',this.name);
}
var person2 = {
    name:'Christina',
    sayHi:sayHi
}
var person1 = {
    name:'ZSZ'
    friend:person2
}

person1.friend.sayHi();

打印是:Christina
因為只有最后一層會確定this指向的是什么,不管有多少層,在判斷this的時候,我們只關(guān)注最后一層。即此處的friend。

隱式綁定有一個大陷阱,綁定很容易丟失(或者說容易給我們造成誤導(dǎo),我們以為this指向的是什么,但是實際上并非如此)。

例子如下:

function sayHi() {
    console.log('Hello,',this.name);
}
var person = {
    name:'ZSZ01',
    sayHi:sayHi
}
var name = 'ZSZ02';
var Hi = person.sayHi; // Hi指向了sayHi的引用
Hi();

打印是 ZSZ02
Hi直接指向了sayHi的引用,在調(diào)用的時候,跟person沒有半毛錢關(guān)系,針對此類問題,我們只需要急著這個格式 XXX.fn(); 如果fn()前如果什么都沒有,那么肯定不是隱式綁定,但是也不一定就是默認綁定。

除了上面這種丟失之外,隱式綁定的丟失是發(fā)生在回調(diào)函數(shù)中(事件回調(diào)也是其中一種),例子如下:


function sayHi() {
    console.log('Hello,',this.name);
}

var person1 = {
    name:'ZSZ01',
    sayHi:function(){
        setTimeout(function(){
            console.log('Hello,',this.name);
        })
    }
}


打印結(jié)果為:

Hello, Wiliam
Hello, Wiliam
Hello, 

第一條輸出很容易理解,setTimeout的回調(diào)函數(shù)中,this使用的是默認綁定,非嚴格模式下,執(zhí)行的是全局對象

第二條輸出是不是有點迷惑了?說好XXX.fun()的時候,fun中的this指向的是XXX呢,為什么這次卻不是這樣了!Why?

其實這里我們可以這樣理解:setTimeout(fn,delay){fn();} 相當(dāng)于是將person2.sayHi賦值給了一個變量,最后執(zhí)行了一個變量,這個時候,sayHi中的this顯然和person2就沒有關(guān)系了。

第三條雖然也是在setTimeout的回調(diào)中,但是我們可以看出,這是執(zhí)行的是person2.sayHi()使用的隱式綁定,因此這是this指向的是person2,跟當(dāng)前的作用域沒有任何關(guān)系

3、硬綁定[顯式綁定]

顯式綁定比較好理解,就是通過call,apply,bind的方式,顯式的指定this所指向的對象。(注意《你不知道的Javascript》中將bind單獨作為了硬綁定講解了)

call,apply和bind的第一個參數(shù),就是對應(yīng)函數(shù)的this所指向的對象。call和apply的作用一樣,只是傳參方式不同。call和apply都會執(zhí)行對應(yīng)的函數(shù),而bind方法不會。

function sayHi(){
    console.log('Hello,',this.name);
}
var person = {
    name:'ZSZ01',
    sayHi:sayHi
}
var name = 'ZSZ02';
var Hi = person.sayHi;
Hi.call(person); // Hi.apply(person)

輸出結(jié)果為: Hello,ZSZ01 因為使用硬綁定明確將this綁定在了person上。

那么,使用了硬綁定,是不是意味著不會出現(xiàn)隱式綁定所遇到的綁定丟失呢?顯然不是這樣的,不信,繼續(xù)往下看。


function sayHi() {
    console.log('Hello,',this.name);
}
var person = {
    name:'ZSZ01',
    sayHi:sayHi,
}
var name = 'ZSZ02';
var Hi = function(fn) {
    fn();
}
Hi.call(person,person.sayHi);

輸出的結(jié)果是 Hello,ZSZ02。原因很簡單,Hi.call(person,person.sayHi);的確是將this綁定到Hi中的this了。但是在執(zhí)行fn的時候,相當(dāng)于直接調(diào)用了sayHi方法(記?。簆erson.sayHi已經(jīng)被賦值給fn了,隱式綁定也丟了),沒有指定this的值,對應(yīng)的是默認綁定。

現(xiàn)在,我們希望綁定不會丟失,要怎么做?很簡單,調(diào)用fn的時候。也給它硬綁定。

function sayHi(){
    console.log('Hello,',this.name);
}
var person = {
    name:'ZSZ01',
    sayHi:sayHi,
}
var name = 'ZSZ02'
var Hi = function(fn) {
    fn.call(this);
}
Hi.call(person,person.sayHi);

此時,輸出結(jié)果為:Hello,ZSZ01,因為person被綁定到Hi函數(shù)中的this上,fn又將這個對象綁定給了sayHi的函數(shù)。這時,sayHi中的this指向的就是person對象。

4、new綁定

javaScript和C++不一樣,并沒有類,在javaScript中,構(gòu)造函數(shù)只是使用new操作符時被調(diào)用的函數(shù),這些函數(shù)和普通的函數(shù)并沒有什么不同,它不屬于某個類,也不可能實例化出一個類。任何一個函數(shù)都可以使用new來調(diào)用,因此其實并不存在構(gòu)造函數(shù),而只有對于函數(shù)的“構(gòu)造調(diào)用”。

使用new來調(diào)用函數(shù),會自動執(zhí)行下面的操作:

1、創(chuàng)建一個新對象
2、將構(gòu)造函數(shù)的作用域賦值給新對象,即this指向這個新對象
3、執(zhí)行構(gòu)造函數(shù)中的代碼
4、返回新對象
因此,我們使用new來調(diào)用函數(shù)的時候,就會把新對象綁定到這個函數(shù)的this上。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容