JavaScript this

對于那些沒有花時間學習 this 綁定機制如何工作的 JavaScript 開發(fā)者來說开财,this 綁定一直是困惑的根源。對于 this 這么重要的機制來說,猜測济欢、試錯、或者盲目地從 Stack Overflow 的回答中復制粘貼小渊,都不是有效或正確利用它的方法法褥,通過這篇文章大家可以更好地認識、理解this酬屉。

目錄:

有關(guān)this的困惑

針對以下兩種寫法半等,打印的this.a為什么會不同揍愁??

var obj = {
  foo: function () { 
    console.log(this.a) 
  },
  a: 1
};

var foo = obj.foo;
var a = 2;

// 方式一
obj.foo() // 1

// 方式二
foo() // 2

這里的this.count和foo.count有什么區(qū)別杀饵?莽囤?

    function foo(num) {
        console.log( "foo: " + num );

        this.count++;
    }
    
    foo.count = 0;
    
    var i;
    
    for (i=0; i<10; i++) {
        if (i > 5) {
            foo( i );
        }
    }
    // foo: 6
    // foo: 7
    // foo: 8
    // foo: 9
    
    console.log( foo.count ); // 0 

如果你對上面的內(nèi)容產(chǎn)生了很大的疑問,那么恭喜你切距,這篇文章非常適合你進一步閱讀朽缎。

我們先給出一個正確的結(jié)論,在后續(xù)講解中我們會直接用到:
this 實際上是在函數(shù)被調(diào)用時建立的一個綁定谜悟,它指向 什么 是完全由函數(shù)被調(diào)用的調(diào)用點來決定的话肖。

這個解釋可能對大家來說非常的含糊,我們接著往后分析:

分析

數(shù)據(jù)存儲結(jié)構(gòu)

首先我們需要了解數(shù)據(jù)的存儲結(jié)構(gòu):

var obj = {a: 5}為例葡幸,

代碼含義:將一個對象賦值給obj最筒;

實際操作:JavaScript引擎會在內(nèi)存里面生成一個{a: 5}的對象,然后將這個對象的內(nèi)存地址賦值給obj蔚叨;實際上obj是一個內(nèi)存的地址(reference)床蜘。

讀取操作:當我們想要讀取obj.a的值,引擎先從obj拿到地址缅叠,然后在從地址找到原始對象悄泥,返回他的a屬性。原始的對象以字典結(jié)構(gòu)保存肤粱,每一個屬性名都對應一個屬性描述對象弹囚。

[圖片上傳失敗...(image-281894-1572599613293)]

代碼分析

[圖片上傳失敗...(image-9d7b58-1572599613293)]


知識點:

調(diào)用點:函數(shù)在代碼中被調(diào)用的位置(不是被聲明的位置)。

怎么判斷this:根據(jù)調(diào)用點我們可以清楚的了解當前的this究竟指向什么领曼。

【怎么判斷調(diào)用點鸥鹉?】

function baz() {
    // 調(diào)用棧是: `baz`
    // 我們的調(diào)用點是 global scope(全局作用域)

    console.log( "baz" );
    bar(); // <-- `bar` 的調(diào)用點
}

function bar() {
    // 調(diào)用棧是: `baz` -> `bar`
    // 我們的調(diào)用點位于 `baz`

    console.log( "bar" );
    foo(); // <-- `foo` 的 call-site
}

function foo() {
    // 調(diào)用棧是: `baz` -> `bar` -> `foo`
    // 我們的調(diào)用點位于 `bar`

    console.log( "foo" );
}

baz(); // <-- `baz` 的調(diào)用點

this的四種常用綁定規(guī)則

默認綁定

function foo() {
    console.log( this.a );
}

var a = 2;

foo(); // 2

隱含綁定

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

obj.foo(); // 2

只有對象屬性引用鏈的最后一層是影響調(diào)用點的:

function foo() {
    console.log( this.a );
}

var obj2 = {
    a: 42,
    foo: foo
};

var obj1 = {
    a: 2,
    obj2: obj2
};

obj1.obj2.foo(); // 42

明確綁定

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2
};

foo.call( obj ); // 2
foo.apply(obj); // 2

new綁定

var a = 10;
function test() {
    a = 5;
    alert(a);
    alert(this.a);
    var a;
    alert(this.a);
    alert(a);
}

test()

new test()

new在創(chuàng)建的時候究竟經(jīng)歷了一些什么?

  1. 一個全新的對象會憑空創(chuàng)建(就是被構(gòu)建)庶骄;
  2. 這個新構(gòu)建的對象會被接入原形鏈([[Prototype]]-linked)毁渗;
  3. 這個新構(gòu)建的對象被設置為函數(shù)調(diào)用的 this 綁定;
  4. 除非函數(shù)返回一個它自己的其他 對象单刁,否則這個被 new 調(diào)用的函數(shù)將 自動 返回這個新構(gòu)建的對象灸异。

這個四個規(guī)則是依次更強的,也就是說new > 明確綁定 > 隱形綁定 > 默認綁定羔飞。

es6箭頭函數(shù)

function foo() {
    setTimeout(() => {
        // 這里的 `this` 是詞法上從 `foo()` 采用
        console.log( this.a );
    },100);
}

var obj = {
    a: 2
};

foo.call( obj ); // 2

箭頭函數(shù)的本質(zhì)是使用廣為人知的詞法作用域來禁止了傳統(tǒng)的 this 機制肺樟,箭頭函數(shù)不會創(chuàng)建自己的this,它只會從自己作用域的上一層繼承this逻淌。

這里的箭頭函數(shù)繼承了上一層的this(obj么伯,這里用了明確綁定),所以最終的this指向了obj.a為2卡儒。

練習

練習一:

var length = 10;
function fn() {
        console.log(this.length);
}

var obj = {
    length: 5,
    method: function(fn) {
        fn();
        arguments[0]();
    }
};

obj.method(fn, 1); 

練習二:

var x = 10;
var foo = {
    x: 20,
    bar: function () {
        var x = 30;
        return this.x;
    }
};

console.log(
    foo.bar(),
    (foo.bar)(),
    (foo.bar = foo.bar)(),
    (foo.bar, foo.bar)()
);

練習三:

var age = 20;
 var person = {
  "age" : 10,
  "getAgeFunc" : function(){
    return function(){
      return this.age;
    };
  }
};
console.log(person.getAgeFunc()());

感謝觀看~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末田柔,一起剝皮案震驚了整個濱河市凫佛,隨后出現(xiàn)的幾起案子抡爹,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件费奸,死亡現(xiàn)場離奇詭異粥血,居然都是意外死亡湿滓,警方通過查閱死者的電腦和手機诗良,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虐骑,“玉大人准验,你說我怎么就攤上這事⊥⒚唬” “怎么了糊饱?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長颠黎。 經(jīng)常有香客問我另锋,道長,這世上最難降的妖魔是什么狭归? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任夭坪,我火速辦了婚禮,結(jié)果婚禮上过椎,老公的妹妹穿的比我還像新娘室梅。我一直安慰自己,他們只是感情好疚宇,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布亡鼠。 她就那樣靜靜地躺著,像睡著了一般敷待。 火紅的嫁衣襯著肌膚如雪间涵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天榜揖,我揣著相機與錄音勾哩,去河邊找鬼。 笑死举哟,一個胖子當著我的面吹牛钳幅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炎滞,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼诬乞!你這毒婦竟也來了册赛?” 一聲冷哼從身側(cè)響起钠导,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎森瘪,沒想到半個月后牡属,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡扼睬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年逮栅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窗宇。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡措伐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出军俊,到底是詐尸還是另有隱情侥加,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布粪躬,位于F島的核電站担败,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏镰官。R本人自食惡果不足惜提前,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泳唠。 院中可真熱鬧狈网,春花似錦、人聲如沸警检。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扇雕。三九已至拓售,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間镶奉,已是汗流浹背础淤。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留哨苛,地道東北人鸽凶。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像建峭,于是被迫代替她去往敵國和親玻侥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354