摘要:不過匿名函數的執行環境具有全局性,因此其對象通常指向。在閉包中使用對象可能會導致一些問題。這個對象還包含一個方法它返回一個匿名函數,而匿名函數又返回,這個匿名函數就是閉包。偽代碼過程在定義匿名函數之前,把對象賦值給了一個名叫的變量。
this對象
前言:最近在細讀Javascript高級程序設計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內容引用自《JavaScript高級程序設計第三版》。
this對象是在運行時基于函數的執行環境綁定:
在全局環境中, this等于window,而當函數被作為某個對象的方法調用時,this就指向了那個對象。
不過匿名函數的執行環境具有全局性,因此其this對象通常指向window。
在閉包中使用this對象可能會導致一些問題。
有時候由于編寫閉包的方式不同,這一點可能不會那么明顯。
// 在全局環境中,this等于window function thisBoundForWindow(){ console.log(this); console.log(this.name); } thisBoundForWindow(); // Window var o = new Object(); o.name = "Shaw"; //當函數被作為某個對象的方法調用時,this就指向了那個對象。 thisBoundForWindow.apply(o); // {name: "Shaw"}; "Shaw" ;
//在閉包中使用this對象可能會導致一些問題。 //有時候由于編寫閉包的方式不同,這一點可能不會那么明顯。 var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { return function() { console.log(this.name); } } } object.getNameFunc()(); // "The Window" /* object.getNameFunc return=> function() { return function() { console.log(this.name); } } => ()調用,還是在全局環境下調用的,所以this.name = window.name => "The Window" */
以上代碼先創建了一個全局變量name,又創建了一個包含name屬性的對象。
這個對象還包含一個方法——getNameFunc(), 它返回一個匿名函數,而匿名函數又返回this.name,這個匿名函數就是閉包。
再來回顧一下“閉包”的定義:
有權訪問另外一個作用域中的變量的函數就是閉包。
由于getNameFunc()返回一個函數,因此調用object.getNameFunc()()就會調用它返回的函數,結果就是控制臺打印出一個字符竄。
然而,這個例子返回的字符竄是"The Window",即全局name變量的值。
那么,如何把this指向例子中的object呢?
把外部作用域的this對象保存在一個閉包能夠訪問到的變量里,就可以讓閉包訪問該對象了。(注意,這種手法,在使用回調函數的時候也經常用到)。
var name = "The Window"; var object = { name: "My Object", getNameFunc: function(){ var that = this; return function() { console.log(that.name); } } } object.getNameFunc()(); // "My Object" /* // 偽代碼過程 object.getNameFunc execute => this = object = that =>function() {console.log(that.name);} => () => that.name = object.name => "My Object" */
在定義匿名函數之前,把this對象賦值給了一個名叫that的變量。
而在定義了閉包之后,閉包也可以訪問這個變量,因為它是我們在包含函數中特意聲明的一個變量。
即使在函數返回之后,that也仍然引用著object, 所以調用Object.getNameFunc()就返回了"My Object"。
在幾種特殊情況下,this的值可能會意外地改變。比如,下面的代碼時修改前面例子的結果。
var name = "The Window"; var object = { name: "My Object", getName: function() { console.log(this.name); } }; object.getName(); // "My Object" (object.getName)(); // "My Object" (object.getName = object.getName)(); // "The Window"
第一行代碼跟平常一樣調用了object.getName(),返回時"My Object",因為this.name就是object.name。
第二行代碼在調用這個方法前給它加上了括號,雖然加上括號之后,就好像是在引用一個函數,但this的值得到了維持,因為object.getName和(object.getName)的定義是相同的。
第三行代碼先執行了一條賦值語句,然后再調用賦值后的結果。因為這個賦值表達式是函數本身,所以this的值得不到維持,結果就返回了"The Window"。
//第三個例子偽代碼 //理解此段代碼,首先要明確一個知識點:賦值語句是有返回值的,返回值就是所賦的值(也就是‘=’右邊的值)。 (object.getName = object.getName)(); // "The Window" (object.getName = function(){ console.log(this.name)})(); (function(){console.log(this.name)})(); //所以this指向window
當然,我們不太可能會像第二行和第三行代碼一樣調用這個方法。暫時理解不了也沒事,這個例子有助于說明即使是語法的細微變化,都有可能意外地改變this值。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98774.html
摘要:另外,的綁定和函數聲明的位置沒有任何關系,之取決于函數的調用方式。請看下面代碼這樣,我們就可以在調用的時候強制把它的綁定到上綁定在傳統的面向類語言中,使用初始化類時會調用類中的構造函數。 關于this 上一章我們講了關于作用域和閉包的相關知識,現在開始新一輪的學習,那就是JavaScript中最復雜的機制之一---this關鍵字。它是一個很特別的關鍵字,被自動定義在所有函數的作用域中。...
摘要:理解的函數基礎要搞好深入淺出原型使用原型模型,雖然這經常被當作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統的類繼承還要強大。中文指南基本操作指南二繼續熟悉的幾對方法,包括,,。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家帶來幫助....(據說是阿里的前端妹子寫的) this 的值到底...
摘要:模擬實現操作符構造函數返回結果創建一個空對象取傳入的第一個參數,即構造函數,并刪除第一個參數。二處理返回值構造函數也是函數,有不同類型返回值。有時候構造函數會返回指定的對象內容,所以要對這部分進行處理。 本文共 1230 字,讀完只需 5 分鐘 寫在前面 最近工作太忙,快接近兩周沒更新博客,總感覺有一些事情等著自己去做,雖然工作內容對自己提升挺大,但我總覺得,一直埋著頭走路,偶爾也...
摘要:之前總結了的一些常見綁定情況前端工程師手冊之的筆記,但是還有一些沒有說到,今天繼續學習一下。參考資料箭頭函數你不知道的上卷 之前總結了this的一些常見綁定情況(【前端工程師手冊】JavaScript之this的筆記),但是還有一些沒有說到,今天繼續學習一下。 es6箭頭函數 先說結論:箭頭函數沒有自己的this,它是根據外層(函數或者全局,后面會說到箭頭函數作為某個對象的方法時的情況...
摘要:第四點也要著重講下,記住構造函數被操作,要讓正常作用最好不能在構造函數里 4) this、new、call和apply的相關問題 講解this指針的原理是個很復雜的問題,如果我們從javascript里this的實現機制來說明this,很多朋友可能會越來越糊涂,因此本篇打算換一個思路從應用的角度來講解this指針,從這個角度理解this指針更加有現實意義。 下面我們看看在ja...
閱讀 3807·2023-04-25 19:07
閱讀 3553·2021-11-22 12:02
閱讀 3138·2021-10-12 10:11
閱讀 3907·2021-09-03 10:49
閱讀 2891·2019-08-30 13:21
閱讀 2997·2019-08-30 11:14
閱讀 2089·2019-08-29 15:40
閱讀 2872·2019-08-28 18:29