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

資訊專欄INFORMATION COLUMN

javascript系列--javascript深入淺出圖解作用域鏈和閉包

Jensen / 3347人閱讀

摘要:變量對象也是有父作用域的。作用域鏈的頂端是全局對象。當函數被調用的時候,作用域鏈就會包含多個作用域對象。當函數要訪問時,沒有找到,于是沿著作用域鏈向上查找,在的作用域找到了對應的標示符,就會修改的值。

一、概要

對于閉包的定義(紅寶書P178):閉包就是指有權訪問另外一個函數的作用域中的變量的函數。

關鍵點:

1、閉包是一個函數

2、能夠訪問另外一個函數作用域中的變量

二、閉包特性

對于閉包有下面三個特性:

1、閉包可以訪問當前函數以外的變量

function getOuter(){
var date = "815";
function getDate(str){

console.log(str + date);  //訪問外部的date

}
return getDate("今天是:"); //"今天是:815"
}
getOuter();

2、即使外部函數已經返回,閉包仍能訪問外部函數定義的變量

function getOuter(){
var date = "815";
function getDate(str){

console.log(str + date);  //訪問外部的date

}
return getDate; //外部函數返回
}
var today = getOuter();
today("今天是:"); //"今天是:815"
today("明天不是:"); //"明天不是:815"

3、閉包可以更新外部變量的值

function updateCount(){
var count = 0;
function getCount(val){

count = val;
console.log(count);

}
return getCount; //外部函數返回
}
var count = updateCount();
count(815); //815
count(816); //816

三、作用域鏈

javascript中有一個執行上下文(execution context)的概念,它定義了變量或函數有權訪問的其他數據,決定它們各自的行為。每一個執行環境都有一個與之關聯的變量對象,環境中定義的所有變量和函數都保存在這個對象中。你可以把它當做Javascript的一個普通對象,但是你只能修改它的屬性,卻不能引用它。

變量對象也是有父作用域的。

作用域鏈定義:當訪問一個變量時,解釋器會首先在當前作用域查找標示符,如果沒有找到,就去父作用域找,直到找到該變量的標示符或者不再存在父作用域了,這就是作用域鏈。

作用域鏈和原型繼承有點類似,但又有點小區別:如果去查找一個普通對象的屬性時,在當前對象和其原型中都找不到時,會返回undefined;但查找的屬性在作用域鏈中不存在的話就會拋出ReferenceError。

作用域鏈的頂端是全局對象。對于全局環境中的代碼,作用域鏈只包含一個元素:全局對象。所以,在全局環境中定義變量的時候,它們就會被定義到全局對象中。當函數被調用的時候,作用域鏈就會包含多個作用域對象。

四、全局環境

關于作用域鏈講得略多(紅皮書上有關于作用域及執行環境的詳細解釋),看一個簡單地例子:

// my_script.js
"use strict";
var foo = 1;
var bar = 2;
在全局環境中,創建了兩個簡單地變量。如前面所說,此時變量對象是全局對象:

執行上述代碼,my_script.js本身會形成一個執行環境,以及它所引用的變量對象。

4.1無嵌套函數

// my_script.js
"use strict";

var foo = 1;
var bar = 2;

function myFunc() {

var a = 1;
var b = 2;
var foo = 3;
console.log("inside myFunc");

}

console.log("outside");
myFunc();
定義時:當myFunc被定義的時候,myFunc的標識符(identifier)就被加到了全局對象中,這個標識符所引用的是一個函數對象(myFunc function object)。

內部屬性[[scope]]指向當前的作用域對象,也就是函數的標識符被創建的時候,我們所能夠直接訪問的那個作用域對象(即全局對象)。

myFunc所引用的函數對象,其本身不僅僅含有函數的代碼,并且還含有指向其被創建的時候的作用域對象。

調用時:當myFunc函數被調用的時候,一個新的作用域對象被創建了。新的作用域對象中包含myFunc函數所定義的本地變量,以及其參數(arguments)。這個新的作用域對象的父作用域對象就是在運行myFunc時能直接訪問的那個作用域對象(即全局對象)。

4.2嵌套函數

當函數返回沒有被引用的時候,就會被垃圾回收器回收。但是對于閉包,即使外部函數返回了,函數對象仍會引用它被創建時的作用域對象。

"use strict";
function createCounter(initial) {
var counter = initial;

function increment(value) {

counter += value;

}

function get() {

return counter;

}

return {

increment: increment,
get: get

};
}

var myCounter = createCounter(100);
console.log(myCounter.get()); // 返回 100

myCounter.increment(5);
console.log(myCounter.get()); // 返回 105
當調用 createCounter(100) 時,內嵌函數increment和get都有指向createCounter(100) scope的引用。假設createCounter(100)沒有任何返回值,那么createCounter(100) scope不再被引用,于是就可以被垃圾回收。

但是createCounter(100)實際上是有返回值的,并且返回值被存儲在了myCounter中,所以對象之間的引用關系如下圖:

即使createCounter(100)已經返回,但是其作用域仍在,并且只能被內聯函數訪問。可以通過調用myCounter.increment() 或 myCounter.get()來直接訪問createCounter(100)的作用域。

當myCounter.increment() 或 myCounter.get()被調用時,新的作用域對象會被創建,并且該作用域對象的父作用域對象會是當前可以直接訪問的作用域對象。

調用get()時,當執行到return counter時,在get()所在的作用域并沒有找到對應的標示符,就會沿著作用域鏈往上找,直到找到變量counter,然后返回該變量。

多帶帶調用increment(5)時,參數value保存在當前的作用域對象。當函數要訪問counter時,沒有找到,于是沿著作用域鏈向上查找,在createCounter(100)的作用域找到了對應的標示符,increment()就會修改counter的值。除此之外,沒有其他方式來修改這個變量。閉包的強大也在于此,能夠存貯私有數據。

創建兩個函數:myCounter1和myCounter2

//my_script.js
"use strict";
function createCounter(initial) {
/ ... see the code from previous example ... /
}

//-- create counter objects
var myCounter1 = createCounter(100);
var myCounter2 = createCounter(200);
關系圖如下

myCounter1.increment和myCounter2.increment的函數對象擁有著一樣的代碼以及一樣的屬性值(name,length等等),但是它們的[[scope]]指向的是不一樣的作用域對象。

五、參考

https://github.com/dwqs/blog/...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109795.html

相關文章

  • 【進階2-1期】深入淺出圖解作用鏈和閉包

    摘要:本期推薦文章從作用域鏈談閉包,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。推薦理由這是一篇譯文,深入淺出圖解作用域鏈,一步步深入介紹閉包。作用域鏈的頂端是全局對象,在全局環境中定義的變量就會綁定到全局對象中。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周開始前端進階的第二期,本周的主題是作用域閉包,今天是第6天。 本...

    levius 評論0 收藏0
  • 【進階2-2期】JavaScript深入之從作用域鏈理解閉包

    摘要:使用上一篇文章的例子來說明下自由變量進階期深入淺出圖解作用域鏈和閉包訪問外部的今天是今天是其中既不是參數,也不是局部變量,所以是自由變量。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第7天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進階計...

    simpleapples 評論0 收藏0
  • 【進階2-3期】JavaScript深入閉包面試題解

    摘要:閉包面試題解由于作用域鏈機制的影響,閉包只能取得內部函數的最后一個值,這引起的一個副作用就是如果內部函數在一個循環中,那么變量的值始終為最后一個值。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第8天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了...

    alanoddsoff 評論0 收藏0
  • 深入執行環境、作用鏈和閉包

    摘要:執行環境對象和作用域鏈執行環境,又稱執行上下文,是指一個函數在執行的時候所能直接引用的變量等的一個集合。為了解釋作用域鏈的機制,我們再來引入一個屬性的概念。而函數的執行環境對象作用域鏈保存了函數在執行時能解析到的變量。 執行環境對象和作用域鏈 執行環境,又稱執行上下文,是指一個函數在執行的時候所能直接引用的變量等的一個集合。 在JavaScript引擎中,執行環境是由一類特殊的對象——...

    gyl_coder 評論0 收藏0
  • 【進階1-3期】JavaScript深入之內存空間詳細圖解

    摘要:進階期理解中的執行上下文和執行棧進階期深入之執行上下文棧和變量對象但是今天補充一個知識點某些情況下,調用堆棧中函數調用的數量超出了調用堆棧的實際大小,瀏覽器會拋出一個錯誤終止運行。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第一期,本周的主題是調用堆棧,今天是第3天。 本計劃一共28期,每期重點攻...

    coordinate35 評論0 收藏0

發表評論

0條評論

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