JavaScript初學者必看“this”

來源:互聯網
上載者:User

標籤:deb   測試   代碼   模式   tps   描述   問題   判斷   情況   

譯者按: JavaScript的this和Java等物件導向語言中的this大不一樣,bind()call()apply()函數更是將this的靈活度進一步延伸。

原文: JavaScript: The Keyword ‘This’ for Beginners

譯者: Fundebug

為了保證可讀性,本文採用意譯而非直譯。另外,本文著作權歸原作者所有,翻譯僅用於學習。

如果對JavaScript的關鍵字this理解不夠深刻,有時候會掉入意想不到的坑。在這裡我們總結了5條通用規則來協助你判斷this到底指向什麼。雖然沒有囊括所有的情況,但日常大部分情況都可以使用這些規則來正確推斷。

  1. this的值通常是由所在函數的執行環境決定,也就是說要看函數是如何被調用的;
  2. 同一個函數每一次調用,this都可能指向不同的對象;
全域對象 (Global Object)

開啟Chrome瀏覽器開發人員面板(Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J),並且輸入:

console.log(this);

 

看看輸出了什嗎?

// Window {}

window對象! 因為在全域範圍下,this指向全域對象。在瀏覽器中全域對象就是window對象。
為了讓你更加清楚理解為什麼this會指向window對象,我們來看另外一個例子:

var myName = ‘Brandon‘;

 

我們可以通過在控制台輸入myName來訪問其值:

myName// 輸出 ‘Brandon‘

 

其實,所有在全域定義的變數都綁定到window對象。我們來做如下測試:

window.myName// 輸出 ‘Brandon‘window.myName === myName// 輸出 true

 

現在我們將this放到函數內部,看看有何效果。

function test(){ return this;}test();

你會發現this依然指向全域的window對象。因為this關鍵字沒有處於一個聲明的對象內部,預設指向全域window對象。這一點可能對於大部分初學者來說有點難以理解。當讀完這篇文章,你就會豁然開朗。
注意:如果在strcit模式下,上面的例子中thisundefined

聲明的對象 (Declared Object)

this關鍵字在一個聲明對象內部使用,其值會被綁定到調用該this的函數的最近的父物件。我們用例子來說明這個問題:

var person = { first: ‘John‘, last: ‘Smith‘, full: function() { console.log(this.first + ‘ ‘ + this.last); }};person.full();// 輸出 ‘John Smith‘

 

在被聲明的對象person中的full函數裡面使用了this, 那麼調用thisfull函數的最近的父物件就是person, 因此,this指向person

為了更好的描述this實際上是指向person對象的,你可以拷貝如下代碼到瀏覽器控制台,將this列印出來。

var person = { first: ‘John‘, last: ‘Smith‘, full: function() { console.log(this); }};person.full();// 輸出 Object {first: "John", last: "Smith", full: function}

我們接下來看一個更複雜的例子:

var person = { first: ‘John‘, last: ‘Smith‘, full: function() { console.log(this.first + ‘ ‘ + this.last); }, personTwo: { first: ‘Allison‘, last: ‘Jones‘, full: function() { console.log(this.first + ‘ ‘ + this.last); } }};

 

在這裡我們有嵌套的對象,在這個時候,this分別指向誰呢? 我們將其列印出來看一看:

person.full();// 輸出 ‘John Smith‘person.personTwo.full();// 輸出 ‘Allison Jones‘

 

你會發現滿足我們前面所描述的規則:其值會被綁定到調用this的函數的最近的父物件。

new關鍵字

當使用new關鍵字構建一個新的對象,this會綁定到這個新對象。我們來看一個例子:

function Car(make, model) { this.make = make; this.model = model;};

根據第一條規則,你可能會推斷this指向全域對象。但是如果我們使用new關鍵字來聲明一個新的變數,Car函數中的this將會綁定一個新的Null 物件,然後初始化this.makethis.model的值。

var myCar = new Car(‘Ford‘, ‘Escape‘);console.log(myCar);// 輸出 Car {make: "Ford", model: "Escape"}

 

callbind, 和 apply

我們可以顯示的在call()bind()apply()中設定this的綁定對象。這三個函數很類似,但是我們需要注意它們微小的區別。

我們來看一個例子:

function add(c, d) { console.log(this.a + this.b + c + d);}add(3,4);// 輸出 NaN

 

add函數輸出NaN, 因為this.athis.b未定義。

現在我們引入對象,並且使用call()apply()來調用:

function add(c, d) { console.log(this.a + this.b + c + d);}var ten = {a: 1, b: 2};add.call(ten, 3, 4);// 輸出 10add.apply(ten, [3,4]);// 輸出 10

 

當我們使用add.call(),第一個參數是this需要綁定的對象,剩下的是add函數本來的參數。
因此,this.a指向ten.a,this.b指向ten.badd.apply()也類似,除了第二個參數是一個數組,用於儲存add函數的參數。

bind()函數和call()類似,但是bind()函數不會立即被調用。bind()函數會返回一個函數,並且將this綁定好。接下來我們來用例子來協助理解bind()函數的應用情境:

var small = { a: 1, go: function(b,c,d){ console.log(this.a+b+c+d); }}var large = { a: 100}

 

執行:

small.go(2, 3, 4);// 輸出 10

 

如果我們想使用large.a的值,而不是small.a呢? 我們可以使用call/apply:

small.go.call(large, 2, 3, 4);// 輸出 109

 

但是,如果我們現在還不知道這三個參數應該傳入什麼值,應該怎麼辦呢? 我們可以使用bind:

var bindTest = small.go.bind(large, 2);

 

如果我們將bindTest在控制台下列印出來,我們會看到:

console.log(bindTest);// 輸出 function (b,c,d){console.log(this.a+b+c+d);}

 

注意:該函數已經將this綁定到large對象,並且傳入了第一個參數b。所以,我們接下來是需要傳入餘下的參數即可:

bindTest(3, 4);// 輸出 109

 

箭頭函數(=>)

因為需要很大的篇幅,我們會專門寫一篇部落格來介紹。

結論

當你讀完這篇部落格,你應該可以理解大多數情況下this指向的對象。
接下來我們來總結一下:

  1. this的值通常是由當前函數的執行環境所決定;
  2. 在全域範圍,this指向全域對象 (window對象);
  3. 當使用new關鍵字聲明,this指向建立對象;
  4. 我們可以使用call()bind()apply()來設定this
  5. 箭頭函數不會綁定this

歡迎加入我們Fundebug的全棧BUG監控交流群: 622902485


 

著作權聲明:轉載時請註明作者Fundebug以及本文地址:https://blog.fundebug.com/2017/05/17/javascript-this-for-beginners/

JavaScript初學者必看“this”

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.