摘要:,對外公開的接口。更需要注意立即執行函數,返回的是一個匿名函數,也是一個閉包,在這里一定要注意一個問題是在進入可執行上下文時創建的。三在方法中,注意如下代碼省略代碼的實際參數是一個自執行匿名函數,這個匿名函數接受了兩個參數,但只返回了。
function DemoFunction(){ this.init = function(){ var func = (function(va){ this.va = va; return function(){ va += this.va; return va; } })(function(va1, va2){ var va3 = va1 + va2; return va1; }(1,2)); console.log(func(20)); this.func = func; console.log(this.func(100)); } } var a = new DemoFunction(); a.init();
首先我們得有如下幾個概念:
執行上下文:每次當控制器轉到ECMAScript可執行代碼時,即會進入一個可執行上下文,參考文獻:深入理解JavaScript系列(11):執行上下文(Execution Contexts)
this:this的創建是在 “進入執行上下文” 時創建的,在代碼執行過程中是不可變的,參考文獻:深入理解JavaScript系列(13):This? Yes,this!
自執行函數:準確來說應該叫:立即調用函數表達式。因為他聲明后即執行,參考文獻:深入理解JavaScript系列(4):立即調用的函數表達式
詳細解釋此段代碼
一、首先看DemoFunction的構造函數這是代碼的重點,第一層代碼可以縮減為如下:
function DemoFunction(){ this.init = function(){ //省略代碼.... } }
表示為DemoFunction的實例提供init方法(聲明:此處有誤導成份,方法應盡可能放在原型鏈接上,也就是prototype上。),對外公開的接口。
二、在init方法中,再次省略代碼如下:var func = (function(va){ this.va = va; return function(){ va += this.va; return va; } })(/*省略代碼...*/); //省略代碼....
上面代碼介紹:
首先定義了一個立即執行函數,并把此函數的執行結果賦值給func。
需要注意立即執行函數中this.va=va這行代碼,由于立即執行函數沒有調用者,所以在進入可執行上下文時,this會被賦值為Global(瀏覽器中為window對象)。
更需要注意立即執行函數,返回的是一個匿名函數,也是一個閉包,在這里一定要注意一個問題:this是在進入可執行上下文時創建的。
三、在init方法中,注意如下代碼:var func = (function(va){ this.va = va; return function(){ va += this.va; return va; } })(function(va1, va2){ var va3 = va1 + va2; return va1; }(1,2)); //省略代碼....
va的實際參數是一個自執行匿名函數,這個匿名函數接受了兩個參數va1,va2,但只返回了va1。以此為據,那么可以確定va的值也就為1。接著就執行this.va=va這句代碼,由于當前this為window,所以參數va的值被賦值到了window的一個叫va的屬性上。
四、在init方法中,加上輸出語句:var func = (function(va){ this.va = va; return function(){ va += this.va; return va; } })(function(va1, va2){ var va3 = va1 + va2; return va1; }(1,2)); console.log(func(20)); this.func = func; console.log(this.func(100)); }
結果分析:
第一個console.log輸出的是func(20),這里一定要注意調用者是沒有具體指定的,此時默認的就是Global(也就是widnow對象),因此輸出為:2
第二個console.log輸出的是this.func(100),可以看到this.func與func是指向同一個函數的引用,但此時的調用者則指定為this,也就是當前對象的實例,因此輸出為:NaN。原因:this(當前對象的實例)作為調用者,在func的函數中va += this.va這句代碼中的this是指向當前對象的實例,但當前對象的實例上是沒有va屬性的。但是va是有值的,當前值為2了。是因為閉包把va值存到內存中了。那么如何讓第二次得到的值也是2呢,結果很簡單,如下:
function DemoFunction(){ this.va = 0; this.init = function(){ var func = (function(va){ this.va = va; return function(){ va += this.va; return va; } })(function(va1, va2){ var va3 = va1 + va2; return va1; }(1,2)); console.log(func(20)); this.func = func; console.log(this.func(100)); } } var a = new DemoFunction(); a.init();
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89849.html
摘要:內網調整引發的歷史記錄修改及的學習由于經常變動導致本地項目的那些存在地址欄的歷史記錄就都失效了突然腦洞大開有沒有辦法修改本地歷史記錄的方法想法是假設我原是新是我歷史記錄有我通過某種辦法強行修改歷史記錄將替換成這樣下次在地址欄輸入他就能自動填 內網IP調整引發的Chrome歷史記錄修改及ShadowRoot的學習 由于IP經常變動, 導致本地項目的那些存在地址欄的歷史記錄就都失效了, 突...
摘要:內網調整引發的歷史記錄修改及的學習由于經常變動導致本地項目的那些存在地址欄的歷史記錄就都失效了突然腦洞大開有沒有辦法修改本地歷史記錄的方法想法是假設我原是新是我歷史記錄有我通過某種辦法強行修改歷史記錄將替換成這樣下次在地址欄輸入他就能自動填 內網IP調整引發的Chrome歷史記錄修改及ShadowRoot的學習 由于IP經常變動, 導致本地項目的那些存在地址欄的歷史記錄就都失效了, 突...
摘要:而為對象時,可用選項如下之所以第三個參數有兩種形態,是在舊版本中只存在一個布爾值,即屬性但隨著時間推移以及發展的需要,需要支持設置更多的特性設置,所以有了選項這個對象傳參,又為了兼容以前的老程序,所以對兩者進行了兼容。 起因 最近在看以前的代碼時,發現年初在熟悉react hooks新特性時寫下了這樣一段代碼: let i = 0; function Test(props) { c...
摘要:舉個栗子中一段簡單的繼承代碼實現使用了,不會報錯這段代碼非常簡單,在子類中使用了關鍵字,編譯時不會報錯,也可以正常執行。參考資料從中的講原型鏈與繼承的靜態屬性和實例屬性 問題引入 最近一直在看原型繼承相關的東西,翻到這么一篇文章: 從ES6中的extends講js原型鏈與繼承 文中有一個點讓我很感興趣,箭頭函數在繼承過程中無法通過super關鍵字獲取,這是為什么呢? 前置知識 MDN上...
摘要:圖示如下而對于引用類型的復制可不是這樣這個復制只是將的引用賦值給,二者是屬于同一個引用,訪問的都是堆內存中的同一個對象,任何一個該引用的變量發生變化,會對其余使用該引用的變量也發生變化。 這兩天自己在寫代碼的時候,出現一個BUG,代碼如下: class Car { constructor(carId) { this.position =...
閱讀 3291·2023-04-26 02:42
閱讀 798·2021-10-09 09:41
閱讀 3235·2021-09-06 15:02
閱讀 758·2019-08-26 10:45
閱讀 485·2019-08-23 15:53
閱讀 743·2019-08-22 18:10
閱讀 555·2019-08-22 18:01
閱讀 3521·2019-08-22 17:34