【成都第一百零七期】JS中this的指向

JS中this的指向

【成都小課堂】

1.背景介紹

2.知識剖析

3.常見問題

4.解決方案

5.編碼實戰

6.擴展思考

7.參考文獻

8.更多討論

1.背景介紹

this是Javascript語言的一個關鍵字。它代表函數運行時,自動生成的一個內部對象。

this是動態綁定的,它可以是全局對象、當前對象或者任意對象(這取決于函數的調用方式)。這就導致了this具備了多重含義,可以使得javascript更靈活的使用。但是,帶來了靈活性的同時也會給我們初學者帶來不少困惑。

2.知識剖析

全局環境中的this

function test() {

console.log(this);

}

test();

總結:在全局作用域中它的this執行當前的全局對象(瀏覽器端是Window,node中是global)

嚴格模式‘use strict’下的this

'use strict';

function test() {

console.log(this);

};

test();

// undefined

原因:this并不會指向全局,而是undefined,這樣的做法是為了消除js中一些不嚴謹的行為。

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

1.作為對象方法調用:this被自然綁定到該對象,也就是說this就指這個上級對象

var point = {

x : 0,

y : 0,

moveTo : function(x, y) {

this.x = this.x + x;

this.y = this.y + y;

}

};

point.moveTo(1, 1)//this綁定到當前對象,即point對象

2.作為函數調用:this被綁定到全局對象

function makeNoSense(x) {

this.x = x;

}

makeNoSense(5);

x;// x已經成為一個值為5的全局變量

3.作為構造函數調用:this綁定到新創建的對象上,也就是說this就指這個新對象

function Point(x, y){

this.x = x;

this.y = y;

}

注:構造函數不使用new調用,則和普通函數一樣。一般地,構造函數首字母大寫

4.使用apply或call調用:在JavaScript中函數也是對象,對象則有方法,apply和call就是函數對象的方法。

function Point(x, y){

this.x = x;

this.y = y;

this.moveTo = function(x, y){

this.x = x;

this.y = y;

}

}

var p1 = new Point(0, 0);

var p2 = {x: 0, y: 0};

p1.moveTo(1, 1);

p1.moveTo.apply(p2, [10, 10]);

3、常見問題

問題一

var obj = {

name: 'qiutc',

foo: function() {

console.log(this);

},

foo2: function() {

console.log(this);

setTimeout(this.foo, 1000);

}

}

obj.foo2();

現象:兩次打印的this不一樣

問題二

'use strict';

function foo() {

console.log(this);

}

setTimeout(foo, 1);

// window

現象:加了嚴格模式,foo調用也沒有指定this,應該是出來undefined,但是這里仍然出現了全局對象

4、解決方案

問題一起因是因為 setTimeout() 將 this.foo 作為了自身的參數,這時候 this.foo 是作為一個fun參數去獲取全局的變量了。

可以這么這么解決:利用閉包的特性來處理

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;因為foo2中的this是指向obj,我們可以先用一個變量_this來儲存,然后在回調函數中使用_this,就可以指向當前的這個對象了

問題二

setTimeout方法在調用傳入函數的時候,如果這個函數沒有指定了的this,那么它會做一個隱式的操作—-自動地注入全局上下文,等同于調用foo.apply(window)而非foo();

5、編碼實戰

對于內部函數,即聲明在另外一個函數體內的函數,這種綁定到全局對象的方式會產生另外一個問題。我們仍然以前面提到的point對象為例,這次我們希望在moveTo方法內定義兩個函數,分別將x,y坐標進行平移。結果可能出乎大家意料,不僅point對象沒有移動,反而多出兩個全局變量x,y

var point = {

x : 0,

y : 0,

moveTo : function(x, y) {

//內部函數

var moveX = function(x) {

this.x = x;//this綁定到了哪里?

};

//內部函數

var moveY = function(y) {

this.y = y;//this綁定到了哪里?

};

moveX(x);

moveY(y);

}

};

point.moveTo(1, 1);

point.x; //==>0

point.y; //==>0

x; //==>1

y; //==>1

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

var point = {

x : 0,

y : 0,

moveTo : function(x, y) {

var that = this;

//內部函數

var moveX = function(x) {

that.x = x;

};

//內部函數

var moveY = function(y) {

that.y = y;

}

moveX(x);

moveY(y);

}

};

point.moveTo(1, 1);

point.x; //==>1

point.y; //==>1

6.擴展思考

問題:如何理解this?

當一個函數被調用時,擁有它的object會作為this傳入。在全局下,就是window or global,其他時候就是相應的object。 也可以看到,call和apply就是利用這一點實現更改this值的

7.參考文獻

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

參考二:JavaScript中的this !

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

參考四:如何理解JavaScript中的this關鍵字?

8、更多討論

this含義為何如此豐富?

理解this的指向有何意義?

答案鏈接


小課堂視頻:


_2017-0512-1904-26_騰訊視頻


PPT鏈接


------------------------------------------------------------------------------------------------------------------------

技能樹.IT修真院

“我們相信人人都可以成為一個工程師,現在開始,找個師兄,帶你入門,掌控自己學習的節奏,學習的路上不再迷茫”。

這里是技能樹.IT修真院,成千上萬的師兄在這里找到了自己的學習路線,學習透明化,成長可見化,師兄1對1免費指導。快來與我一起學習吧 !

http://www.jnshu.com/login/1/96029204

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容