javascript成神之路(4):深入理解this關鍵字,是的就是this
摘要:如果你真的理解了this是什麼,那麼你的web幾乎所向披靡(文章後面有驚喜,不要錯過)
很多程式設計師會這麼認為,this關鍵字與物件導向程式開發緊密相關,其完全指向由構造器新建立的物件。在ECMAScript規範中也是這樣實現的,但正如我們將看到那樣,在ECMAScript中,this並不限於只用來指向新建立的物件。還有很多新功能特性
一、定義
this代表當前物件,說明this是在某種特定的情況下才是成立的,它是執行上下文的一個屬性。
activeExecutionContext = { AEC: {…}, this: thisVal };
這裡AEC是我們討論的變數物件。this與上下文中可執行程式碼的型別有直接關係,this值在進入上下文時確定,並且在上下文執行期間永久不變。
二、全域性程式碼中的this
在全域性程式碼中,this始終是全域性物件本身,這樣就有可能間接的引用到它了。
// 顯示定義全域性物件的屬性 this.ab = 10; // global.ab = 10 alert(ab); // 10 // 通過賦值給一個無標示符隱式 bb = 20; alert(this.bb); // 20 // 也是通過變數宣告隱式宣告的 // 因為全域性上下文的變數物件是全域性物件自身 var cc = 30; alert(this.cc); // 30
三、函式程式碼中的this
在這時候this值的首要特點是它不是靜態的繫結到一個函式。this是進入上下文時確定,在一個函式程式碼中,這個值在每一次完全不同,但是在程式碼執行時的this值是不變的,也就是說,因為它不是一個變數,就不可能為其分配一個新值。
var F = {y: 10}; var Bar = { y: 20, test: function () { alert(this === Bar); // true alert(this.y); // 20 this = F; // 錯誤,任何時候不能改變this的值 alert(this.y); // 如果不出錯的話,應該是10,而不是20 } }; // 在進入上下文的時候 // this被當成Bar物件 B.test(); // true, 20 F.test = Bar.test; // 不過,這裡this依然不會是foo // 儘管呼叫的是相同的function F.test(); // false, 10
在我們通常的函式呼叫中,this是由啟用上下文程式碼的呼叫者來提供的,即呼叫函式的父上下文(parent context )。this取決於呼叫函式的方式,正是呼叫函式的方式影響了呼叫的上下文中的this值,沒有別的什麼可以看到,即使是正常的全域性函式也會被呼叫方式的不同形式啟用,這些不同的呼叫方式導致了不同的this值。例如:
function F() { alert(this); } F(); // global alert(F === F.prototype.constructor); // true // 但是同一個function的不同的呼叫表示式,this是不同的 F.prototype.constructor(); // F.prototype
那麼,呼叫函式的方式如何影響this值?請看下面
四、引用型別
引用型別的值只有兩種情況: 1、當我們處理一個標示符時,2、或者一個屬性訪問器
在一個函式上下文中,this由呼叫者提供,由呼叫函式的方式來決定。如果呼叫括號()的左邊是引用型別的值,this將設為引用型別值的base物件(base object),在其他情況下(與引用型別不同的任何其它屬性),這個值為null。不過,實際不存在this的值為null的情況,因為當this的值為null的時候,其值會被隱式轉換為全域性物件,例如:
function F() { return this; } F(); // global
我們看到在呼叫括號的左邊是一個引用型別值(因為F是一個標示符)
var fooReference = { base: global, propertyName: `foo` };
相應地,this也設定為引用型別的base物件。即全域性物件
var F = { B: function () { return this; } }; F.B(); // F
我們再次擁有一個引用型別,其base是F物件,在函式B啟用時用作this。
var FB = { base: F, propertyName: `B` };
五、作為構造器呼叫的函式中的this
還有一個與this值相關的情況是在函式的上下文中,這是一個建構函式的呼叫。
unction A() { alert(this); // “a”物件下建立一個新屬性 this.x = 10; } var a = new A(); alert(a.x); // 10
new運算子呼叫“A”函式的內部的[[Construct]] 方法,接著,在物件建立後,呼叫內部的[[Call]] 方法。 所有相同的函式“A”都將this的值設定為新建立的物件。
六、函式呼叫中手動設定this
在函式原型中定義的兩個方法允許去手動設定函式呼叫的this值。它們是.apply和.call方法。他們用接受的第一個引數作為this值,this 在呼叫的作用域中使用。這兩個方法的區別很小,對於.apply,第二個引數必須是陣列(或者是類似陣列的物件,如arguments,反過來,.call能接受任何引數。兩個方法必須的引數是第一個——this。
var dog = { say() { console.log(this) } } var cat = {} dog.say.call(cat)
其中this通過call被繫結到了cat上
七、箭頭函式
它的this指向與普通函式有很大的不同。箭頭函式內部的 this 是詞法作用域,由上下文確定。簡單說就是箭頭函式中的 this 只和定義它時候的作用域的 this 有關,而與在哪裡以及如何呼叫它無關,同時它的 this 指向是不可改變的。
var obj = { x: 10, foo: function() { var fn = () => { return () => { return () => { console.log(this); //Object {x: 10} console.log(this.x); //10 } } } fn()()(); } } obj.foo();
對於箭頭函式還需要注意一點,就是它的this確定後不會改變。使用call、apply、bind也無法改變它的this,因此使用它們傳入的第一個引數無效。但是後面新增的引數值還是有效的。
原文釋出時間:2018年01月10日
作者:技術金三胖
本文來源:開源中國 如需轉載請聯絡原作者
相關文章
- 深入理解synchronized關鍵字synchronized
- 深入理解copy關鍵字
- 完全理解JavaScript中的this關鍵字JavaScript
- 揭祕JavaScript中“神祕”的this關鍵字JavaScript
- C++ 的 new 關鍵字深入理解C++
- 深入理解Java中的volatile關鍵字Java
- Java面試題,深入理解final關鍵字Java面試題
- 深入理解Swift中static和class關鍵字Swift
- 深入彙編指令理解Java關鍵字volatileJava
- 深入理解Java中的final關鍵字Java
- JavaScript this關鍵字JavaScript
- [JavaScript] this 關鍵字JavaScript
- 4關鍵字
- 手把手教你深入理解this關鍵字及其使用
- 淺顯易懂的理解JavaScript中的this關鍵字JavaScript
- 完全理解關鍵字this
- JavaScript中this關鍵字JavaScript
- javascript的this關鍵字JavaScript
- Java課堂篇4_關鍵字this、static的理解Java
- JAVA static關鍵字理解Java
- final關鍵字深入解析
- 深入分析 synchronized 關鍵字synchronized
- 深入解析volatile關鍵字
- Java併發專題(三)深入理解volatile關鍵字Java
- 用自然語言的角度理解JavaScript中的this關鍵字JavaScript
- javascript中的with關鍵字JavaScript
- 快速理解 volatile 關鍵字
- python:理解關鍵字—yieldPython
- 深入理解Java記憶體模型JMM與volatile關鍵字Java記憶體模型
- [譯] 深入淺出 JavaScript 關鍵詞 -- thisJavaScript
- 深入理解 JavaScript 非同步系列(4)—— GeneratorJavaScript非同步
- JavaScript 複習之 this關鍵字JavaScript
- JavaScript 關鍵字和保留字JavaScript
- Javascript中this關鍵字詳解JavaScript
- javascript 作用域和 this 關鍵字JavaScript
- 大資料成神之路大資料
- 兩張圖理解volatile關鍵字
- Java關鍵字volatile的理解Java