摘要:申明與賦值立即執行的函數表達式,通過創建一個函數,并且立即執行,來構造一個新的域,從而控制的范圍。函數接受一個的形參,該參數是一個對象引用,并執行了。在最新的標準中,引入了一個新概念。
筆記說明
重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的可以加入winter的專欄學習【原文有winter的語音】,如有侵權請聯系我,郵箱:kaimo313@foxmail.com。一、函數執行過程相關知識 二、閉包(closure)
閉包其實只是一個綁定了執行環境的函數,閉包與普通函數的區別是,它攜帶了執行的環境,就像人在外星中需要自帶吸氧的裝備一樣,這個函數也帶有在程序中生存的環境。2.1、古典的閉包
環境部分
環境
標識符列表
表達式部分
2.2、JavaScript 中閉包
環境部分
環境:函數的詞法環境(執行上下文的一部分)
標識符列表:函數中用到的未申明的變量
表達式部分:函數體
三、執行上下文(執行的基礎設施)定義:JavaScript 標準把一段代碼(包括函數),執行所需的所有信息定義為執行上下文。3.1、在 ES3 中
scope:作用域,也常常被叫做作用域鏈
variable object:變量對象,用于存儲變量的對象
this value:this 值
3.2、在 ES5 中lexical environment:詞法環境,當獲取變量時使用
variable environment:變量環境,當聲明變量時使用
this value:this 值
3.3、在 ES2018 中lexical environment:詞法環境,當獲取變量或者 this 值時使用
variable environment:變量環境,當聲明變量時使用
code evaluation state:用于恢復代碼執行位置
Function:執行的任務是函數時使用,表示正在被執行的函數
ScriptOrModule:執行的任務是腳本或者模塊時使用,表示正在被執行的代碼
Realm:使用的基礎庫和內置對象實例
Generator:僅生成器上下文有這個屬性,表示當前生成器
3.4、函數執行過程所需信息var b = {} let c = 1 this.a = 2;
正確執行上面代碼需知道的信息:
1、var 把 b 聲明到哪里
2、b 表示哪個變量
3、b 的原型是哪個對象
4、let 把 c 聲明到哪里
5、this 指向哪個對象
而這些信息就是執行上下文給出來的,下面用 var 聲明與賦值,let,realm分析執行上下文提供的信息。
3.5、var 申明與賦值1、立即執行的函數表達式(IIFE),通過創建一個函數,并且立即執行,來構造一個新的域,從而控制 var 的范圍。
var b = 1
2、加括號讓函數變成函數表達式
(function(){ var a; //code }()); (function(){ var a; //code })();
注意:括號有個缺點,那就是如果上一行代碼不寫分號,括號會被解釋為上一行代碼最末的函數調用。
一些不加分號的代碼風格規范,會要求在括號前面加上分號。
;(function(){ var a; //code }()) ;(function(){ var a; //code })()
winter 推薦用 void 關鍵字,語義上 void 運算表示忽略后面表達式的值,變成 undefined。
void function(){ var a; //code }();
特別注意:var 的特性會導致聲明的變量和被賦值的變量是兩個 b,JavaScript 中有特例,那就是使用 with 的時候,如代碼塊二,我們先講一下代碼一
with 語句的原本用意是為逐級的對象訪問提供命名空間式的速寫方式. 也就是在指定的代碼區域, 直接通過節點名稱調用對象。
// 代碼塊一 var obj = { a: 1, b: 2, c: 3 }; // 比如要改對應的值,一般的寫法是重復寫了3次obj obj.a = 5; obj.b = 6; obj.c = 7; console.log(obj) // {a: 5, b: 6, c: 7} // 用 with 快捷方式 with (obj) { a = 5; b = 6; c = 7; } console.log(obj) // {a: 5, b: 6, c: 7} // 接下來看一下 with 導致的數據泄露 function kaimo(obj) { with (obj) { a = 1; } } var k1 = { a: 2 }; var k2 = { b: 3 } kaimo(k1); console.log(k1.a); // 1 kaimo(k2); console.log(k2.a); // undefined console.log(a); // 1 (a被泄漏到全局作用域上)
上述代碼分析:
1、創建了 k1 、k2 兩個對象。其中一個有 a 屬性,另外一個沒有。
2、kaimo(obj) 函數接受一個 obj 的形參,該參數是一個對象引用,并執行了 with(obj) {...}。
3、在 with 塊內部,將 2 賦值給了 a。
4、將 k1 傳遞進去,a = 2 賦值操作找到了 k1.a 并將 2 賦值給它。
5、當 k2 傳遞進去,k2 并沒有 a 的屬性,因此不會創建這個屬性,k2.a 保持 undefined。
問題:為什么對 k2 的操作會導致數據的泄漏呢?
首先稍微講一下:JavaScript中的 LHS 和 RHS 查詢
LHS(Left-hand Side)引用和 RHS(Right-hand Side)引用。通常是指等號(賦值運算)的左右邊的引用。
console.log(gg)
比如上面這個打印,先查找并取得 gg 的值,然后將它打印出來 gg 的引用是一個 RHS 引用,沒有賦予操作
gg = 666;
上面是對 gg 的引用是一個 LHS 引用,為賦值操作找到目標
綜上:
1、當傳遞 k2 給 with 時,with 所聲明的作用域是 k2, 從這個作用域開始對 a 進行 LHS 查詢。
2、k2 的作用域、kaimo(…) 的作用域和全局作用域中都沒有找到標識符 a,因此在非嚴格模式下,會自動在全局作用域創建一個全局變量),在嚴格模式下,會拋出 ReferenceError 異常。
// 代碼塊二 var b; void function(){ var env = {b:1}; b = 2; console.log("In function b:", b); with(env) { var b = 3; console.log("In with b:", b); } }(); console.log("Global b:", b); // 輸出結果如下: // In function b: 2 // In with b: 3 // Global b: undefined3.6、let
let 是 ES6 開始引入的新的變量聲明模式。
winter 簡單統計了下,以下語句會產生 let 使用的作用域:
for、 if、 switch、 try/catch/finally。3.7、Realm
在最新的標準(9.0)中,JavaScript 引入了一個新概念 Realm。有道詞典上的意思是:"領域,范圍;王國"。Realm 中包含一組完整的內置對象,而且是復制關系。
var iframe = document.createElement("iframe") document.documentElement.appendChild(iframe) iframe.src="javascript:var b = {};" var b1 = iframe.contentWindow.b; var b2 = {}; console.log(b1, b2); // {} {} console.log(typeof b1, typeof b2); // 谷歌輸出: object object 火狐輸出:undefined object console.log(b1 instanceof Object, b2 instanceof Object); //false true
上面代碼可以看到,在瀏覽器環境中獲取來自兩個 Realm 的對象,由于 b1、 b2 由同樣的代碼 {} 在不同的 Realm 中執行,所以表現出了不同的行為。
個人總結總的來說,這一篇一臉懵逼(_(:3」∠)_),要去看看《你不知道的JavaScript》才行了。。。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/55050.html
摘要:申明與賦值立即執行的函數表達式,通過創建一個函數,并且立即執行,來構造一個新的域,從而控制的范圍。函數接受一個的形參,該參數是一個對象引用,并執行了。在最新的標準中,引入了一個新概念。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的可以加入winter的專欄...
摘要:申明與賦值立即執行的函數表達式,通過創建一個函數,并且立即執行,來構造一個新的域,從而控制的范圍。函數接受一個的形參,該參數是一個對象引用,并執行了。在最新的標準中,引入了一個新概念。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的可以加入winter的專欄...
摘要:實現狀態機可能產生四種輸入元素,其中只有兩種,狀態機的第一個狀態就是根據第一個輸入字符來判斷進入了哪種狀態用函數表示狀態,用表示狀態的遷移關系,用值表示下一個狀態。運行狀態機輸出結果四語法分析語法分析根據每一個產生式來寫一個函數。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點...
閱讀 1117·2021-11-25 09:43
閱讀 1639·2021-09-13 10:25
閱讀 2592·2021-09-09 11:38
閱讀 3399·2021-09-07 10:14
閱讀 1714·2019-08-30 15:52
閱讀 641·2019-08-30 15:44
閱讀 3572·2019-08-29 13:23
閱讀 1973·2019-08-26 13:33