摘要:因為關鍵字沒有處于一個聲明的對象內部,默認指向全局對象。這一點可能對于大部分初學者來說有點難以理解。函數會返回一個函數,并且將綁定好。自從年雙十一正式上線,累計處理了億錯誤事件,得到了金山軟件百姓網等眾多知名用戶的認可。
譯者按: JavaScript的this和Java等面向對象語言中的this大不一樣,bind()、call()和apply()函數更是將this的靈活度進一步延伸。
原文: JavaScript: The Keyword ‘This’ for Beginners
譯者: Fundebug
為了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原作者所有,翻譯僅用于學習。
如果對JavaScript的關鍵字this理解不夠深刻,有時候會掉入意想不到的坑。在這里我們總結了5條通用規(guī)則來幫助你判斷this到底指向什么。雖然沒有囊括所有的情況,但日常大部分情況都可以使用這些規(guī)則來正確推斷。
this的值通常是由所在函數的執(zhí)行環(huán)境決定,也就是說要看函數是如何被調用的;
同一個函數每一次調用,this都可能指向不同的對象;
全局對象 (Global Object)打開Chrome瀏覽器開發(fā)者面板(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
現(xiàn)在我們將this放到函數內部,看看有何效果。
function test(){ return this; } test();
你會發(fā)現(xiàn)this依然指向全局的window對象。因為this關鍵字沒有處于一個聲明的對象內部,默認指向全局window對象。這一點可能對于大部分初學者來說有點難以理解。當讀完這篇文章,你就會豁然開朗。
注意:如果在strcit模式下,上面的例子中this為undefined。
當this關鍵字在一個聲明對象內部使用,其值會被綁定到調用該this的函數的最近的父對象。我們用例子來說明這個問題:
var person = { first: "John", last: "Smith", full: function() { console.log(this.first + " " + this.last); } }; person.full(); // 輸出 "John Smith"
在被聲明的對象person中的full函數里面使用了this, 那么調用this的full函數的最近的父對象就是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"
你會發(fā)現(xiàn)滿足我們前面所描述的規(guī)則:其值會被綁定到調用this的函數的最近的父對象。
new關鍵字當使用new關鍵字構建一個新的對象,this會綁定到這個新對象。我們來看一個例子:
function Car(make, model) { this.make = make; this.model = model; };
根據第一條規(guī)則,你可能會推斷this指向全局對象。但是如果我們使用new關鍵字來聲明一個新的變量,Car函數中的this將會綁定一個新的空對象,然后初始化this.make和this.model的值。
var myCar = new Car("Ford", "Escape"); console.log(myCar); // 輸出 Car {make: "Ford", model: "Escape"}call, bind, 和apply
我們可以顯示的在call(),bind(),apply()中設置this的綁定對象。這三個函數很類似,但是我們需要注意它們微小的區(qū)別。
我們來看一個例子:
function add(c, d) { console.log(this.a + this.b + c + d); } add(3,4); // 輸出 NaN
add函數輸出NaN, 因為this.a和this.b未定義。
現(xiàn)在我們引入對象,并且使用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); // 輸出 10 add.apply(ten, [3,4]); // 輸出 10
當我們使用add.call(),第一個參數是this需要綁定的對象,剩下的是add函數本來的參數。
因此,this.a指向ten.a,this.b指向ten.b。add.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 }
執(zhí)行:
small.go(2, 3, 4); // 輸出 10
如果我們想使用large.a的值,而不是small.a呢? 我們可以使用call/apply:
small.go.call(large, 2, 3, 4); // 輸出 109
但是,如果我們現(xiàn)在還不知道這三個參數應該傳入什么值,應該怎么辦呢? 我們可以使用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指向的對象。
接下來我們來總結一下:
this的值通常是由當前函數的執(zhí)行環(huán)境所決定;
在全局作用域,this指向全局對象 (window對象);
當使用new關鍵字聲明,this指向新建對象;
我們可以使用call(), bind(), apply()來設置this;
箭頭函數不會綁定this。
關于FundebugFundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java實時BUG監(jiān)控。 自從2016年雙十一正式上線,F(xiàn)undebug累計處理了9億+錯誤事件,得到了Google、360、金山軟件、百姓網等眾多知名用戶的認可。歡迎免費試用!
版權聲明轉載時請注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/05/17/javascript-this-for-beginners/
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/83179.html
摘要:譯者按箭頭函數看上去只是語法的變動,其實也影響了的作用域。打開瀏覽器開發(fā)者控制臺,輸入我們將變量綁定到一個箭頭函數,該函數有一個參數返回?;蛘哒f箭頭函數不會改變本來的綁定。最后,結束刷屏的打印總結箭頭函數寫代碼擁有更加簡潔的語法不會綁定。 譯者按: 箭頭函數看上去只是語法的變動,其實也影響了this的作用域。 原文: JavaScript: Arrow Functions for B...
摘要:然而,不會在年的基礎上加,而只是表示年。閉包這是一個經典的面試題雖然期望輸出,然而實際上卻不會。因為第行的沒有在正確的環(huán)境下執(zhí)行。 譯者按: 漫漫編程路,總有一些坑讓你淚流滿面。 原文: Who said javascript was easy ? 譯者: Fundebug 為了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原作者所有,翻譯僅用于學習。 這里我們針對JavaScri...
摘要:數組的方法方法創(chuàng)建一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素??蛇x,執(zhí)行函數時的值。刪除所有的鍵值對,沒有返回值。返回一個布爾值,表示某個鍵是否在當前對象之中。 說明 JavaScript數組去重這個問題,經常出現(xiàn)在面試題中,以前也寫過一篇數組去重的文章,(JavaScript 數組去重的多種方法原理詳解)但感覺代碼還是有點不夠簡單,今天和大家再說兩種方法,代碼...
摘要:數組的方法方法創(chuàng)建一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素??蛇x,執(zhí)行函數時的值。刪除所有的鍵值對,沒有返回值。返回一個布爾值,表示某個鍵是否在當前對象之中。 說明 JavaScript數組去重這個問題,經常出現(xiàn)在面試題中,以前也寫過一篇數組去重的文章,(JavaScript 數組去重的多種方法原理詳解)但感覺代碼還是有點不夠簡單,今天和大家再說兩種方法,代碼...
閱讀 3526·2023-04-25 17:35
閱讀 2599·2021-11-24 09:39
閱讀 2538·2021-10-18 13:32
閱讀 3424·2021-10-11 10:58
閱讀 1643·2021-09-26 09:55
閱讀 6176·2021-09-22 15:47
閱讀 972·2021-08-26 14:15
閱讀 3476·2019-08-30 15:55