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

資訊專欄INFORMATION COLUMN

夯實基礎(chǔ)-作用域與閉包

daydream / 3000人閱讀

摘要:作用域分類作用域共有兩種主要的工作模型。換句話說,作用域鏈是基于調(diào)用棧的,而不是代碼中的作用域嵌套。詞法作用域詞法作用域中,又可分為全局作用域,函數(shù)作用域和塊級作用域。

一篇鞏固基礎(chǔ)的文章,也可能是一系列的文章,梳理知識的遺漏點,同時也探究很多理所當然的事情背后的原理。

為什么探究基礎(chǔ)?因為你不去面試你就不知道基礎(chǔ)有多重要,或者是說當你的工作經(jīng)歷沒有亮點的時候,基礎(chǔ)就是檢驗你好壞的一項指標。

JS基礎(chǔ)都會有哪些考點:閉包,繼承,深拷貝,異步編程等一些常見考點,為什么無論是當我還是個學生的時候被面試還是到現(xiàn)在當面試官去考別人,都還是問這些?項目從jQuery都過渡到React全家桶了,js還是考這些?

因為這些知識點很典型,一個知識點弄懂需要先把很多前置的其他的知識點弄懂。比如閉包,閉包背后就有作用域,變量提升,函數(shù)提升,垃圾收集機制等知識點。所以這些知識點往往能以點概面,考察很多基礎(chǔ)的東西。

先來看看閉包(Closure)。

文章里提到了一些知識點:

JS編譯運行過程

詞法作用域與動態(tài)作用域

作用域鏈順序

變量與函數(shù)提升

閉包的應用

JS編譯原理 基本概念

與JAVA,C++,C等靜態(tài)語言不同,JavaScript是不需要編譯的。在JAVA中,程序員寫的JAVA代碼要被編譯器編譯成機器語言,然后執(zhí)行。

編譯

一般程序中的一段源代碼在執(zhí)行之前會經(jīng)歷三個步驟,統(tǒng)稱為“編譯”:

分詞/詞法分析(Tokenizing/Lexing)
這個過程會將由字符組成的字符串分解成(對編程語言來說)有意義的代碼塊,這些代碼塊被稱為詞法單元(token)。例如,考慮程序 var a = 2;。這段程序通常會被分解成為下面這些詞法單元:var、a、=、2 、;。空格是否會被當作詞法單元,取決于空格在這門語言中是否具有意義。

解析/語法分析(Parsing)
這個過程是將詞法單元流(數(shù)組)轉(zhuǎn)換成一個由元素逐級嵌套所組成的代表了程序語法結(jié)構(gòu)的樹。這個樹被稱為“抽象語法樹”(Abstract Syntax Tree,AST)。var a = 2; 的抽象語法樹中可能會有一個叫作 VariableDeclaration 的頂級節(jié)點,接下來是一個叫作 Identifier(它的值是 a)的子節(jié)點,以及一個叫作 AssignmentExpression的子節(jié)點。AssignmentExpression 節(jié)點有一個叫作 NumericLiteral(它的值是 2)的子節(jié)點。

代碼生成

將 AST 轉(zhuǎn)換為可執(zhí)行代碼的過程稱被稱為代碼生成。這個過程與語言、目標平臺等息息相關(guān)。拋開具體細節(jié),簡單來說就是有某種方法可以將 var a = 2; 的 AST 轉(zhuǎn)化為一組機器指令,用來創(chuàng)建一個叫作 a 的變量(包括分配內(nèi)存等),并將一個值儲存在 a 中。

解釋器

JavaScript則不同,JavaScript中對應編譯的部分叫做解釋器(Interpreter)。這兩者的區(qū)別用一句話來概括就是:編譯器是將源代碼編譯為另外一種代碼(比如機器碼,或者字節(jié)碼),而解釋器是直接解析并將代碼運行結(jié)果輸出。

編譯運行過程

JavaScript編譯運行過程中有三個重要的角色:引擎,編譯器,作用域。三者互相配合這樣工作:

源代碼被編譯器處理,進行詞法和語法分析,將編譯出來的變量、方法、數(shù)據(jù)等存儲到作用域,然后將編譯出來的機器代碼交給引擎處理。

作用域負責收集并維護由所有聲明的標識符(變量)組成的一系列查詢,并實施一套非常嚴格的規(guī)則,確定當前執(zhí)行的代碼對這些標識符的訪問權(quán)限。

引擎運行來處理這些機器代碼,遇到變量、方法、數(shù)據(jù)等去作用域中尋找,并執(zhí)行。

舉個例子:

var a = 1;

這段代碼交給解釋器之后:

編譯器運行源代碼,識別出聲明變量var a,編譯器詢問作用域是否已經(jīng)有一個該名稱的變量存在于同一個作用域的集合中。如果是,編譯器會忽略該聲明,繼續(xù)進行編譯;否則它會要求作用域在當前作用域的集合中分配內(nèi)存聲明一個新的變量,并命名為 a。

編譯器將上述代碼編譯成機器代碼并交給引擎執(zhí)行。

引擎運行時從作用域獲取a,如果沒有a則拋出異常,有的話則將a賦值1。

上述代碼在執(zhí)行過程中開起來就好像:

var a;
a = 1;
這不就是很熟悉的變量提升嗎,但是為什么會有變量提升呢,可以理解為代碼的聲明和賦值是分別在編譯和運行時執(zhí)行,兩者之間的數(shù)據(jù)銜接全靠作用域(事實上并不是這樣,后面會提到)。
異常

這里我們很熟悉,有兩種異常:編譯異常,運行異常。

編譯異常

編譯器在編譯的時候發(fā)生錯誤,編譯停止比如:

很明顯編譯器無法知道將1賦值給誰,沒法寫出對應的機器語言,編譯停止。

運行異常

引擎在運行時候發(fā)生錯誤,例如:

引擎向作用域獲取a,但是編譯器未在作用域中聲明a,運行報錯。

聲明了a,并將a賦值為1,但是a無法運行,運行報錯。

LHS查詢 RHS查詢

RHS 查詢與簡單地查找某個變量的值別無二致,而 LHS 查詢則是試圖找到變量的容器本身,從而可以對其賦值。

ES5 中引入了“嚴格模式”。同正常模式,或者說寬松 / 懶惰模式相比,嚴格模式在行為上
有很多不同。其中一個不同的行為是嚴格模式禁止自動或隱式地創(chuàng)建全局變量。因此,在
嚴格模式中 LHS 查詢失敗時,并不會創(chuàng)建并返回一個全局變量,引擎會拋出同 RHS 查詢
失敗時類似的 ReferenceError 異常。

接下來,如果 RHS 查詢找到了一個變量,但是你嘗試對這個變量的值進行不合理的操作,
比如試圖對一個非函數(shù)類型的值進行函數(shù)調(diào)用,或著引用 null 或 undefined 類型的值中的
屬性,那么引擎會拋出另外一種類型的異常,叫作 TypeError。

垃圾收集

和C#、Java一樣JavaScript有自動垃圾回收機制,也就是說執(zhí)行環(huán)境會負責管理代碼執(zhí)行過程中使用的內(nèi)存,在開發(fā)過程中就無需考慮內(nèi)存分配及無用內(nèi)存的回收問題了。

JavaScript垃圾回收的機制很簡單:找出不再使用的變量,然后釋放掉其占用的內(nèi)存,但是這個過程不是時時的,因為其開銷比較大,所以垃圾回收器會按照固定的時間間隔周期性的執(zhí)行。

變量生命周期

什么叫不再使用的變量?不再使用的變量也就是生命周期結(jié)束的變量,當然只可能是局部變量,全局變量的生命周期直至瀏覽器卸載頁面才會結(jié)束。局部變量只在函數(shù)的執(zhí)行過程中存在,而在這個過程中會為局部變量在?;蚨焉戏峙湎鄳目臻g,以存儲它們的值,然后再函數(shù)中使用這些變量,直至函數(shù)結(jié)束(閉包特殊)。

一旦函數(shù)結(jié)束,局部變量就沒有存在必要了,可以釋放它們占用的內(nèi)存。貌似很簡單的工作,為什么會有很大開銷呢?這僅僅是垃圾回收的冰山一角,就像剛剛提到的閉包,貌似函數(shù)結(jié)束了,其實還沒有,垃圾回收器必須知道哪個變量有用,哪個變量沒用,對于不再有用的變量打上標記,以備將來回收。用于標記無用的策略有很多,常見的有兩種方式:標記清除和 引用計數(shù),這里介紹一下標記清除:

標記清除(mark and sweep)

這是JavaScript最常見的垃圾回收方式,當變量進入執(zhí)行環(huán)境的時候,比如函數(shù)中聲明一個變量,垃圾回收器將其標記為“進入環(huán)境”,當變量離開環(huán)境的時候(函數(shù)執(zhí)行結(jié)束)將其標記為“離開環(huán)境”。至于怎么標記有很多種方式,比如特殊位的反轉(zhuǎn)、維護一個列表等,這些并不重要,重要的是使用什么策略,原則上講不能夠釋放進入環(huán)境的變量所占的內(nèi)存,它們隨時可能會被調(diào)用的到。

垃圾回收器會在運行的時候給存儲在內(nèi)存中的所有變量加上標記,然后去掉環(huán)境中的變量以及被環(huán)境中變量所引用的變量(閉包),在這些完成之后仍存在標記的就是要刪除的變量了,因為環(huán)境中的變量已經(jīng)無法訪問到這些變量了,然后垃圾回收器相會這些帶有標記的變量機器所占空間。

大部分瀏覽器都是使用這種方式進行垃圾回收,只是垃圾收集的時間間隔不同。

作用域(scope)
作用域負責收集并維護由所有聲明的標識符(變量)組成的一系列查詢,并實施一套非常嚴格的規(guī)則,確定當前執(zhí)行的代碼對這些標識符的訪問權(quán)限。
作用域分類

作用域共有兩種主要的工作模型。第一種是最為普遍的,被大多數(shù)編程語言所采用的詞法作用域,我們會對這種作用域進行深入討論。另外一種叫作動態(tài)作用域,仍有一些編程語言在使用(比如 Bash 腳本、Perl 中的一些模式等)。

詞法作用域

詞法作用域是由你在寫代碼時將變量和塊作用域?qū)懺谀睦飦頉Q定的,因此當詞法分析器處理代碼時會保持作用域不變(大部分情況下是這樣的)。

動態(tài)作用域

動態(tài)作用域并不關(guān)心函數(shù)和作用域是如何聲明以及在何處聲明的,只關(guān)心它們從何處調(diào)用。換句話說,作用域鏈是基于調(diào)用棧的,而不是代碼中的作用域嵌套。

JavaScript中大部分場景都是詞法作用域,函數(shù)中的this則是動態(tài)作用域,我們先仔細討論詞法作用域。

詞法作用域

詞法作用域中,又可分為全局作用域,函數(shù)作用域塊級作用域。

全局作用域

默認進入的就是全局作用域,在瀏覽器上全局作用域通常都被掛載到windows上。

函數(shù)作用域

函數(shù)作用域的含義是指,屬于這個函數(shù)的全部變量都可以在整個函數(shù)的范圍內(nèi)使用及復用(事實上在嵌套的作用域中也可以使用)。

var a = 1;

function fn () { // 函數(shù)作用域起點
    var a = 2;
    
    console.log(a);
} // 函數(shù)作用域終點

fn(); // 函數(shù)作用域這行業(yè)是,因為涉及到參數(shù)傳值

console.log(a);
塊級作用域

很常見,簡單來說用{}來包裹起來的,通??梢詮陀玫拇a就是,比如for循環(huán),switch case,while等等。

for(var i=0; i<10; i++){ // 塊作用域
    console.log(i);
} // 塊作用域

var a = 1;
switch (a) { // 塊作用域
    case 1: { // 塊作用域
        // ....
    }
    case 2: { // 塊作用域
        // ....
    }
    default: { // 塊作用域
        // ....
    }
}

while (a) { // 塊作用域
  // ....     
}

{ // 硬寫了一個塊作用域
    let a = 2;
    console.log(a);
}

看一個例子:

function func (a) {
    var b = a * 2;
    
    function foo (c) {
        console.log(a, b, c);   
    }
    
    foo(b*3)
    
    {
        let a = 2;
        console.log(a); // 2
    }
}

func(1); // 1,2,3

通過上面這個例子我們來分析:

func被定義在了默認的全局作用域,全局作用域只有 func;

func函數(shù)創(chuàng)造了一個函數(shù)作用域,在函數(shù)體內(nèi)定義的變量被定義在了函數(shù)作用域內(nèi):a,b,foo;

foo函數(shù)又創(chuàng)造了一個函數(shù)作用域,里面有:c

{}創(chuàng)造了一個塊級作用域,里面使用let定義了一個a,這里的變量有:a

動態(tài)作用域

在詞法作用域中,函數(shù)運行時遇到變量,回去在其詞法作用域中尋找對應變量,而在動態(tài)作用域中,則是根據(jù)當前運行情況來確定,最常見的就是this關(guān)鍵字。

var b = 1;
var c = 123;

function fn (a) {
    console.log(a);
    console.log(b);
    console.log(this.c);
}

fn("hello");

var obj = {
    b: 2,
    c: 12,
    fn: fn
}

var o = {
    obj: obj
}

obj.fn("world");

o.obj.fn("!");

fn分別在全局作用域中執(zhí)行,和obj的屬性執(zhí)行。

變量a是fn的函數(shù)作用域中定義的,屬于詞法作用域范疇;

變量b沒有在函數(shù)作用域中定義,向上尋找,在全局作用域中找到,也是詞法作用域范疇;

this.c屬于動態(tài)作用域,函數(shù)執(zhí)行的時候順著調(diào)用棧動態(tài)尋找,this總是指向調(diào)用函數(shù)者。

作用域鏈(scope chain)

不同作用域之間是如何協(xié)作的,這就涉及到了作用域鏈。

作用域查找會在找到第一個匹配的標識符時停止。在多層的嵌套作用域中可以定義同名的標識符,這叫作“遮蔽效應”(內(nèi)部的標識符“遮蔽”了外部的標識符)。拋開遮蔽效應,作用域查找始終從運行時所處的最內(nèi)部作用域開始,逐級向外或者說向上進行,直到遇見第一個匹配的標識符為止。

不同作用域之間是可以嵌套的,所有的局部作用域都在全局作用域這個大容器之中,作用域之間的嵌套關(guān)系就好比堆棧和出棧。

還是上面的例子:

func函數(shù)被定義在了全局作用域上,所以func函數(shù)內(nèi)的變量作用域鏈為:[func函數(shù)作用域,全局作用域];

foo函數(shù)被定義在了foo函數(shù)內(nèi),兩個作用域互相嵌套,foo函數(shù)的作用域就是:[foo函數(shù)作用域,func函數(shù)作用域,全局作用域];

{}在func函數(shù)內(nèi)定義了一個塊級作用域:[塊級作用域,func函數(shù)作用域,全局作用域]。

在每個作用域內(nèi)查找變量,如果對于的作用域內(nèi)無法找到變量,則去其作用域鏈的上一級查找,直到找到第一個結(jié)果返回,否則返回undefined。

如果多個作用域內(nèi)有相同名稱的變量,則會找到距離當前作用域最近的變量。

提升(hoisting)

一開始編譯運行過程的時候我們就知道了JS中存在變量提升,實際上分成兩種情況:變量聲明提升和函數(shù)聲明提升。

變量聲明提升
通常JS引擎會在正式執(zhí)行之前先進行一次預編譯,在這個過程中,首先將變量聲明及函數(shù)聲明提升至當前作用域的頂端,然后進行接下來的處理。

這個我們應該很熟悉了,舉個例子:

console.log(a); // undefined
var a = 1;
console.log(a); // 1

按照閱讀邏輯,在a聲明之前調(diào)用a,會發(fā)生RHS異常,從而觸發(fā)ReferenceError。

但是實際運行的時候,并沒有報錯,因為上面的代碼看起來被編譯成了:

var a;
console.log(a);
a = 1;
console.log(a);

這樣理解看起來是不是就很合理了。

但是值得注意的是,變量提升只會提升至本作用域最頂端,而不會夸作用域:

var foo = 3;

function func () {

    var foo = foo || 5;

    console.log(foo); // 5
}

func();

在func里面的是函數(shù)作用域,全局作用域的一個子集,所以在函數(shù)作用域中調(diào)用變量foo應該就近尋找當前作用域內(nèi)有無變量,找到一個即停止尋找。上述代碼看起來:

var foo = 3;

function func () {
    var foo;
    
    foo = foo || 5;

    console.log(foo); // 5
}

func();
函數(shù)聲明提升

與變量聲明類似的,函數(shù)在聲明的時候也會發(fā)生提升的情況:

func(); // "hello world"

function func () {
    console.log("hello world");
}

相似的,如果在同一個作用域中存在多個同名函數(shù)聲明,后面出現(xiàn)的將會覆蓋前面的函數(shù)聲明;

對于函數(shù),除了使用上面的函數(shù)聲明,更多時候,我們會使用函數(shù)表達式,下面是函數(shù)聲明和函數(shù)表達式的對比:

console.log(foo1);
//函數(shù)聲明
function foo1() {
    console.log("function declaration");
}

console.log(foo2);
//匿名函數(shù)表達式
var foo2 = function() {
    console.log("anonymous function expression");
};

console.log(bar);
console.log(foo3);
//具名函數(shù)表達式
var foo3 = function bar() {
    console.log("named function expression");
};
console.log(bar);

JavaScript中的函數(shù)是一等公民,函數(shù)聲明的優(yōu)先級最高,會被提升至當前作用域最頂端。上述的例子可以發(fā)現(xiàn):只有函數(shù)聲明的時候,才會發(fā)生變量提升,函數(shù)無論是匿名函數(shù)/具名函數(shù)表達式,均不會發(fā)生函數(shù)聲明提升。

兩者優(yōu)先級

兩者同時存在提升,那個優(yōu)先級更高:

console.log(a);
var a = 1;
function a () {
    console.log("hello");
}

console.log(b);
function b () {
    console.log("hello");
}
var b = 1;

上面例子可以看到,當變量和函數(shù)同名的時候,無論誰聲明在后,都是函數(shù)的優(yōu)先級最高,變量為函數(shù)讓路。

為什么提升

至于變量提升的原因:Note 4. Two words about “hoisting”

閉包

經(jīng)過前面知識點鋪墊之后,終于來到了閉包。

function closure () {
    var a = 1;
    
    function result () {
        return a;
    }
    
    return result;
}

closure()();

上面這個例子是個很常見的閉包,變量a在函數(shù)closure內(nèi),不應該在其作用域外被訪問,但是通過返回result函數(shù)實現(xiàn)了在外部訪問到了a,這就是一個簡單的閉包。

事實上閉包的定義:(wiki pedia)

閉包,又稱詞法閉包(Lexical Closure)或函數(shù)閉包(function closures),是引用了自由變量的函數(shù)。這個被引用的自由變量將和這個函數(shù)一同存在,即使已經(jīng)離開了創(chuàng)造它的環(huán)境也不例外。

簡單說就是,函數(shù)內(nèi)定義了一個引用了其作用域內(nèi)變量的函數(shù),然后將該函數(shù)當做一個值傳遞到其他地方,該函數(shù)在運行的時候,雖然運行環(huán)境已經(jīng)不是其詞法作用域,但是還可以訪問到其詞法作用域中的變量。

或者說我們可以這樣理解:

本質(zhì)上無論何時何地,如果將函數(shù)(訪問它們各自的詞法作用域)當作第一級的值類型并到處傳遞,你就會看到閉包在這些函數(shù)中的應用。在定時器、事件監(jiān)聽器、Ajax 請求、跨窗口通信、Web Workers 或者任何其他的異步(或者同步)任務中,只要使用了回調(diào)函數(shù),實際上就是在使用閉包!

這里關(guān)鍵點:函數(shù),函數(shù)引用了其作用域內(nèi)的變量,在其詞法作用域外被調(diào)用。來看一些常見的例子:

function closure () {
    var a = 1;
    
    function result () {
        return a;
    }
    
    window.result = result;
}

closure();
result();

上面例子的變形,closure不在return result,而是掛載到window對象上。很顯然result的詞法作用域在不是全局作用域,滿足閉包的條件,也是一個閉包。

function wait(message) {
    setTimeout( function timer() {
        console.log( message );
    }, 1000 );
}
wait( "Hello, closure!" );

這個有點意思,延遲很常見。timer的詞法作用域是[wait函數(shù)作用域,全局作用域],wait里面起了一個延遲隊列任務,timer被當做參數(shù)傳遞到了延遲里,而timer里面還調(diào)用了message。這樣的話,wait執(zhí)行結(jié)束之后并不會被內(nèi)存回收,1s之后,timer執(zhí)行,其詞法作用域都還在,滿足閉包條件,是一個閉包。

練習

一道經(jīng)典題目:輸出結(jié)果

for(var i = 0; i<5; i++){
    setTimeout(function(){
        console.log(i);
    }, 100);
}

代碼運行之后,打印5個5。這里setTimeout定義之后不會被立即執(zhí)行,而是加入到隊列中延遲執(zhí)行,執(zhí)行的時候運行匿名函數(shù),匿名函數(shù)打印i,i不在匿名函數(shù)作用域中,順著作用域鏈向上尋找,在全局作用域中找到i,這時候的i已經(jīng)是5了,所以均打印5。

這里變形一下:還保留for循環(huán),以及setTimeout形式,要求結(jié)果輸出0,1,2,3,4,怎么改?

很多種方法,我們分成不同方向去考慮:

1. 使用塊級作用域

變量i實際上是個全局作用域變量,for循環(huán),每次都重復聲明i,可以使用塊級作用域,聲明不同的塊級作用域中的變量:

for(let i = 0; i<5; i++){
    setTimeout(function(){
        console.log(i);
    }, 100);
}

或者,賦值轉(zhuǎn)換:

for(var i = 0; i<5; i++){
    let a = i;
    setTimeout(function(){
        console.log(a);
    }, 100);
}

這樣的話,匿名函數(shù)執(zhí)行的時候,函數(shù)作用域內(nèi)沒有i,去塊級作用域?qū)ふ襥,找到并返回結(jié)果,并不會直接尋找到全局作用域。

2. 閉包

閉包應該是最容易想到的,因為他的場景滿足在其詞法作用域外被調(diào)用,怎么使用閉包:立即執(zhí)行函數(shù)(IIFE)

for(var i = 0; i<5; i++){
    (function(i){
        setTimeout(function(){
            console.log(i);
        }, 100);
    })(i);
}

立即執(zhí)行函數(shù)創(chuàng)造了一個新的匿名函數(shù)作用域,這個作用域內(nèi)的i是定義的時候傳進來的,settimeout函數(shù)執(zhí)行時候線上尋找到該作用域,并打印變量。

3.bind函數(shù)

或者使用bind函數(shù)可以直接更改匿名函數(shù)的作用域:

for(var i = 0; i<5; i++){
    setTimeout(function(i){
        console.log(i);
    }.bind(this, i), 100);
}

4.奇技淫巧

只針對這個題目,可以使用進棧出棧保持順序:

var arr = [];

for(var i = 0; i<5; i++){
    arr.unshift(i);
    
    setTimeout(function(){
        console.log(arr.pop());
    }, 100);
}
參考

《你所不知道的JavaScript》

《JavaScript高級程序設(shè)計》

JavaScript系列文章:變量提升和函數(shù)提升

JavaScript深入之閉包

閉包

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/94301.html

相關(guān)文章

  • Js基礎(chǔ)知識(三) - 作用域與閉包

    摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內(nèi)部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創(chuàng)建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質(zhì)上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經(jīng)理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...

    lemanli 評論0 收藏0
  • Js基礎(chǔ)知識(三) - 作用域與閉包

    摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內(nèi)部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創(chuàng)建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質(zhì)上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經(jīng)理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...

    XFLY 評論0 收藏0
  • Js基礎(chǔ)知識(三) - 作用域與閉包

    摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內(nèi)部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創(chuàng)建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質(zhì)上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經(jīng)理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...

    tanglijun 評論0 收藏0
  • Js基礎(chǔ)知識(三) - 作用域與閉包

    摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內(nèi)部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創(chuàng)建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質(zhì)上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經(jīng)理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...

    lmxdawn 評論0 收藏0

發(fā)表評論

0條評論

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