JavaScript之this指標深入詳解
javascript中的this含義非常豐富,它可以是全域性物件,當前物件或者是任意物件,這都取決於函式的呼叫方式。函式有以下幾種呼叫方式:作為物件方法呼叫、作為函式呼叫、作為建構函式呼叫、apply或call呼叫。
物件方法呼叫
作為物件方法呼叫的時候,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 物件
這裡我想強調一點內容,就是this是在函式執行的時候去獲取對應的值,而不是函式定義時。即使是物件方法呼叫,如果該方法的函式屬性以函式名的形式傳入別的作用域,也會改變this的指向。我舉一個例子:
var a = { aa : 0, bb : 0, fun : function(x,y){ this.aa = this.aa + x; this.bb = this.bb + y; } }; var aa = 1; var b = { aa:0, bb:0, fun : function(){return this.aa;} } a.fun(3,2); document.write(a.aa);//3,this指向物件本身 document.write(b.fun());//0,this指向物件本身 (function(aa){//注意傳入的是函式,而不是函式執行的結果 var c = aa(); document.write(c);//1 , 由於fun在該處執行,導致this不再指向物件本身,而是這裡的window })(b.fun);
這樣就明白了吧。這是一個容易混淆的地方。
函式呼叫
函式也可以直接被呼叫,這個時候this被繫結到了全域性物件。
var x = 1; function test(){ this.x = 0; } test(); alert(x); //0
但這樣就會出現一些問題,就是在函式內部定義的函式,其this也會指向全域性,而和我們希望的恰恰相反。程式碼如下:
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
我們會發現不但我們希望的移動呢效果沒有完成,反而會多出兩個全域性變數。那麼如何解決呢?只要要進入函式中的函式時將this儲存到一個變數中,再運用該變數即可。程式碼如下:
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
建構函式呼叫
在javascript中自己建立建構函式時可以利用this來指向新建立的物件上。這樣就可以避免函式中的this指向全域性了。
var x = 2; function test(){ this.x = 1; } var o = new test(); alert(x); //2
apply或call呼叫
這兩個方法可以切換函式執行的上下文環境,也就是改變this繫結的物件。apply和call比較類似,區別在於傳入引數時一個要求是陣列,一個要求是分開傳入。所以我們以apply為例:
<pre name="code" class="html">var name = "window"; var someone = { name: "Bob", showName: function(){ alert(this.name); } }; var other = { name: "Tom" }; someone.showName(); //Bob someone.showName.apply(); //window someone.showName.apply(other); //Tom
可以看到,正常訪問物件中方法時,this指向物件。使用了apply後,apply無引數時,this的當前物件是全域性,apply有引數時,this的當前物件就是該引數。
箭頭函式呼叫
這裡需要補充一點內容,就是在下一代javascript標準ES6中的箭頭函式的 this始終指向函式定義時的 this,而非執行時。我們通過一個例子來理解:
var o = { x : 1, func : function() { console.log(this.x) }, test : function() { setTimeout(function() { this.func(); }, 100); } }; o.test(); // TypeError : this.func is not a function
上面的程式碼會出現錯誤,因為this的指向從o變為了全域性。我們需要修改上面的程式碼如下:
var o = { x : 1, func : function() { console.log(this.x) }, test : function() { var _this = this; setTimeout(function() { _this.func(); }, 100); } }; o.test();
通過使用外部事先儲存的this就行了。這裡就可以利用到箭頭函式了,我們剛才說過,箭頭函式的 this始終指向函式定義時的 this,而非執行時。所以我們將上面的程式碼修改如下:
var o = { x : 1, func : function() { console.log(this.x) }, test : function() { setTimeout(() => { this.func() }, 100); } }; o.test();
這回this就指向o了,我們還需要注意一點的就是這個this是不會改變指向物件的,我們知道call和apply可以改變this的指向,但是在箭頭函式中是無效的。
var x = 1, o = { x : 10, test : () => this.x }; o.test(); // 1 o.test.call(o); // 依然是1
這樣就可以明白各種情況下this繫結物件的區別了。
相關文章
- JavaScript之原型深入詳解JavaScript原型
- JavaScript(1)之——this指標JavaScript指標
- 指標詳解指標
- JavaScript進階之(一) this指標JavaScript指標
- 詳解c++指標的指標和指標的引用C++指標
- JavaScript之this詳解JavaScript
- 指標的詳細講解指標
- C語言指標詳解(一)C語言指標
- C語言指標詳解(二)C語言指標
- c++ 智慧指標用法詳解C++指標
- 深入理解Go系列一之指標變數Go指標變數
- 玩轉 JavaScript 之詳解 thisJavaScript
- Javascript之字串拼接詳解JavaScript字串
- 陣列,函式與指標 詳解陣列函式指標
- 深入理解 Golang 指標Golang指標
- JavaScript物件導向修改標籤頁詳解JavaScript物件
- C++指標的概念解讀 超詳細C++指標
- C指標和陣列的關係詳解指標陣列
- JavaScript——深入瞭解thisJavaScript
- 一文詳盡系列之模型評估指標模型指標
- 【進階1-3期】JavaScript深入之記憶體空間詳細圖解JavaScript記憶體圖解
- Go高階特性 12 | 指標詳解:在什麼情況下應該使用指標?Go指標
- 深入理解mysql之left join 使用詳解MySql
- JavaScript this詳解JavaScript
- 深入理解Javascript之PromiseJavaScriptPromise
- 深入理解Javascript之ModuleJavaScript
- VC++深入詳解--之複習筆記(一)C++筆記
- VC++深入詳解--之複習筆記(二)C++筆記
- 深入理解 Javascript 之 作用域JavaScript
- 深入理解Javascript之Execution ContextJavaScriptContext
- 深入理解JavaScript之Event LoopJavaScriptOOP
- 換個角度看 JavaScript 中的 (this) => { 整理 (JavaScript 深入之從 ECMAScript 規範解讀 this ) }JavaScript
- JavaScript Promise 詳解JavaScriptPromise
- 詳解JavaScript原型JavaScript原型
- JavaScript事件詳解JavaScript事件
- C++智慧指標之shared_ptr與右值引用(詳細)C++指標
- 效能之nmon(硬體指標)指標
- JVM之壓縮指標(CompressedOops)JVM指標OOP
- 深入解析Go非型別安全指標:技術全解與最佳實踐Go型別指標