【成都小課堂162期】JS中THIS的指向

1.背景介紹

this是Javascript語(yǔ)言的一個(gè)關(guān)鍵字。它代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象。

this是動(dòng)態(tài)綁定的,它可以是全局對(duì)象、當(dāng)前對(duì)象或者任意對(duì)象(這取決于函數(shù)的調(diào)用方式)。這就導(dǎo)致了this具備了多重含義,可以使得javascript更靈活的使用。但是,帶來(lái)了靈活性的同時(shí)也會(huì)給我們初學(xué)者帶來(lái)不少困惑。

2.知識(shí)剖析

全局環(huán)境中的this

functiontest(){console.log(this);? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? test();

總結(jié):在全局作用域中它的 this 執(zhí)行當(dāng)前的全局對(duì)象(瀏覽器端是 Window,node 中是 global)

嚴(yán)格模式 ‘use strict’下的this

'use strict';functiontest(){console.log(this);? ? ? ? ? ? ? ? ? };? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? test();// undefined

在javascritp中,不一定只有對(duì)象方法的上下文中才有this, 全局函數(shù)調(diào)用和其他的幾種不同的上下文中也有this指代。 它可以是全局對(duì)象、當(dāng)前對(duì)象或者任意對(duì)象,這完全取決于函數(shù)的調(diào)用方式。JavaScript 中函數(shù)的調(diào)用有以下幾種方式:作為對(duì)象方法調(diào)用,作為函數(shù)調(diào)用,作為構(gòu)造函數(shù)調(diào)用,和使用 apply 或 call 調(diào)用。

原因:this 并不會(huì)指向全局,而是 undefined,這樣的做法是為了消除 js 中一些不嚴(yán)謹(jǐn)?shù)男袨?/p>

1.作為對(duì)象方法調(diào)用:this 被自然綁定到該對(duì)象,也就是說(shuō)this就指這個(gè)上級(jí)對(duì)象

varpoint = {? ? ? ? ? ? ? ? x :0,? ? ? ? ? ? ? ? y :0,? ? ? ? ? ? ? ? moveTo :function(x, y){this.x =this.x + x;this.y =this.y + y;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? };? ? ? ? ? ? ? ? point.moveTo(1,1)//this 綁定到當(dāng)前對(duì)象,即 point 對(duì)象

2.作為函數(shù)調(diào)用:this被綁定到全局對(duì)象

functionmakeNoSense(x){this.x = x;? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? makeNoSense(5);? ? ? ? ? ? ? ? ? x;// x 已經(jīng)成為一個(gè)值為 5 的全局變量

3.作為構(gòu)造函數(shù)調(diào)用:this 綁定到新創(chuàng)建的對(duì)象上,也就是說(shuō)this就指這個(gè)新對(duì)象

functionPoint(x, y){this.x = x;this.y = y;? ? ? ? ? ? ? ? }

注:構(gòu)造函數(shù)不使用new調(diào)用,則和普通函數(shù)一樣。一般地,構(gòu)造函數(shù)首字母大寫(xiě)

4.使用 apply 或 call 調(diào)用:在 JavaScript 中函數(shù)也是對(duì)象,對(duì)象則有方法,apply 和 call 就是函數(shù)對(duì)象的方法。

functionPoint(x, y){this.x = x;this.y = y;this.moveTo =function(x, y){this.x = x;this.y = y;? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }varp1 =newPoint(0,0);varp2 = {x:0, y:0};? ? ? ? ? ? ? ? ? ? p1.moveTo(1,1);? ? ? ? ? ? ? ? ? ? p1.moveTo.apply(p2, [10,10]);

3、常見(jiàn)問(wèn)題

問(wèn)題一

varobj = {? ? ? ? ? ? ? ? ? name:'qiutc',? ? ? ? ? ? ? ? ? foo:function(){console.log(this);? ? ? ? ? ? ? ? ? },? ? ? ? ? ? ? ? ? foo2:function(){console.log(this);? ? ? ? ? ? ? ? ? ? setTimeout(this.foo,1000);? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? obj.foo2();

現(xiàn)象:兩次打印的this不一樣

問(wèn)題二

'use strict';functionfoo(){console.log(this);? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? setTimeout(foo,1);// window

現(xiàn)象:加了嚴(yán)格模式,foo 調(diào)用也沒(méi)有指定 this,應(yīng)該是出來(lái)undefined,但是這里仍然出現(xiàn)了全局對(duì)象

4、解決方案

問(wèn)題一可以這么這么解決:利用 閉包 的特性來(lái)處理

var obj = {name:'qiutc',? ? ? ? ? ? ? ? ? ? ? foo: function() {? ? ? ? ? ? ? ? ? ? ? ? console.log(this);? ? ? ? ? ? ? ? ? ? ? },? ? ? ? ? ? ? ? ? ? ? foo2: function() {? ? ? ? ? ? ? ? ? ? ? ? console.log(this);? ? ? ? ? ? ? ? ? ? ? ? var_this= this;? ? ? ? ? ? ? ? ? ? ? ? setTimeout(function() {? ? ? ? ? ? ? ? ? ? ? ? ? console.log(this);// Windowconsole.log(_this);// Object {name: "qiutc"}},1000);? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? obj.foo2();

可以看到直接用 this 仍然是 Window;因?yàn)?foo2 中的 this 是指向 obj,我們可以先用一個(gè)變量 _this 來(lái)儲(chǔ)存,然后在回調(diào)函數(shù)中使用 _this,就可以指向當(dāng)前的這個(gè)對(duì)象了

問(wèn)題二

setTimeout 方法在調(diào)用傳入函數(shù)的時(shí)候,如果這個(gè)函數(shù)沒(méi)有指定了的 this,那么它會(huì)做一個(gè)隱式的操作—-自動(dòng)地注入全局上下文,等同于調(diào)用 foo.apply(window) 而非 foo();

5、編碼實(shí)戰(zhàn)

問(wèn)題一可以這么這么解決:利用 閉包 的特性來(lái)處理 var obj = { name: 'qiutc', foo: function() { console.log(this); }, foo2: function() { console.log(this); var _this = this; setTimeout(function() { console.log(this); // Window console.log(_this); // Object {name: "qiutc"} }, 1000); } } obj.foo2(); 可以看到直接用 this 仍然是 Window;因?yàn)?foo2 中的 this 是指向 obj,我們可以先用一個(gè)變量 _this 來(lái)儲(chǔ)存,然后在回調(diào)函數(shù)中使用 _this,就可以指向當(dāng)前的這個(gè)對(duì)象了

對(duì)于內(nèi)部函數(shù),即聲明在另外一個(gè)函數(shù)體內(nèi)的函數(shù),這種綁定到全局對(duì)象的方式會(huì)產(chǎn)生另外一個(gè)問(wèn)題。我們?nèi)匀灰郧懊嫣岬?的 point 對(duì)象為例,這次我們希望在 moveTo 方法內(nèi)定義兩個(gè)函數(shù),分別將 x,y 坐標(biāo)進(jìn)行平移。結(jié)果可能出乎大家意 料,不僅 point 對(duì)象沒(méi)有移動(dòng),反而多出兩個(gè)全局變量 x,y

這屬于 JavaScript 的設(shè)計(jì)缺陷,正確的設(shè)計(jì)方式是內(nèi)部函數(shù)的 this 應(yīng)該綁定到其外層函數(shù)對(duì)應(yīng)的對(duì)象上,為了規(guī)避這一設(shè) 計(jì)缺陷,聰明的 JavaScript 程序員想出了變量替代的方法,約定俗成,該變量一般被命名為 that。

6.擴(kuò)展思考

問(wèn)題:如何理解this?

當(dāng)一個(gè)函數(shù)被調(diào)用時(shí),擁有它的object會(huì)作為this傳入。在全局下,就是window or global,其他時(shí)候就是相應(yīng)的object。 也可以看到,call和apply就是利用這一點(diǎn)實(shí)現(xiàn)更改this 值的

7.參考文獻(xiàn)

參考一:深入淺出 JavaScript 中的 this

參考二:JavaScript 中的 this !

參考三:JavaScript中的this用法與指向

參考四:如何理解 JavaScript 中的 this 關(guān)鍵字?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 葡萄藤PPT JS中this的指向 大家好,我是IT修真院鄭州分院第6期的學(xué)員王棟,一枚正直、純潔、善良的前端程序...
    17064閱讀 633評(píng)論 0 2
  • JS中this的指向 【成都小課堂】 1.背景介紹 2.知識(shí)剖析 3.常見(jiàn)問(wèn)題 4.解決方案 5.編碼實(shí)戰(zhàn) 6.擴(kuò)...
    何華颯閱讀 403評(píng)論 0 0
  • 大家好,我是IT修真院成都分院第5期的學(xué)員,一枚正直純潔善良的web程序員 一.背景介紹: 在Java語(yǔ)言中,th...
    張王王閱讀 548評(píng)論 0 0
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,923評(píng)論 18 139
  • android o 今日(2017年08月22日)正式發(fā)布,作為android程序員第一反應(yīng)就是:啊,老紙又要適配...
    李汪汪汪俠閱讀 224評(píng)論 0 0