国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

重學前端學習筆記(十八)--JavaScript的閉包和執行上下文

silencezwm / 1347人閱讀

摘要:申明與賦值立即執行的函數表達式,通過創建一個函數,并且立即執行,來構造一個新的域,從而控制的范圍。函數接受一個的形參,該參數是一個對象引用,并執行了。在最新的標準中,引入了一個新概念。

筆記說明
重學前端是程劭非(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、varb 聲明到哪里

2、b 表示哪個變量

3、b 的原型是哪個對象

4、letc 聲明到哪里

5、this 指向哪個對象

而這些信息就是執行上下文給出來的,下面用 var 聲明與賦值,letrealm分析執行上下文提供的信息。

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 的特性會導致聲明的變量和被賦值的變量是兩個 bJavaScript 中有特例,那就是使用 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中的 LHSRHS 查詢

LHSLeft-hand Side)引用和 RHSRight-hand Side)引用。通常是指等號(賦值運算)的左右邊的引用。
console.log(gg)

比如上面這個打印,先查找并取得 gg 的值,然后將它打印出來 gg 的引用是一個 RHS 引用,沒有賦予操作

gg = 666;

上面是對 gg 的引用是一個 LHS 引用,為賦值操作找到目標

綜上

1、當傳遞 k2with 時,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: undefined
3.6、let
letES6 開始引入的新的變量聲明模式。

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

相關文章

  • 重學前端學習筆記十八)--JavaScript閉包執行下文

    摘要:申明與賦值立即執行的函數表達式,通過創建一個函數,并且立即執行,來構造一個新的域,從而控制的范圍。函數接受一個的形參,該參數是一個對象引用,并執行了。在最新的標準中,引入了一個新概念。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的可以加入winter的專欄...

    liaorio 評論0 收藏0
  • 重學前端學習筆記十八)--JavaScript閉包執行下文

    摘要:申明與賦值立即執行的函數表達式,通過創建一個函數,并且立即執行,來構造一個新的域,從而控制的范圍。函數接受一個的形參,該參數是一個對象引用,并執行了。在最新的標準中,引入了一個新概念。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的可以加入winter的專欄...

    caikeal 評論0 收藏0
  • 重學前端學習筆記(二十八)--通過四則運算解釋器快速理解編譯原理

    摘要:實現狀態機可能產生四種輸入元素,其中只有兩種,狀態機的第一個狀態就是根據第一個輸入字符來判斷進入了哪種狀態用函數表示狀態,用表示狀態的遷移關系,用值表示下一個狀態。運行狀態機輸出結果四語法分析語法分析根據每一個產生式來寫一個函數。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點...

    Crazy_Coder 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<