資源描述:
《javascript從作用域鏈談閉包_javascript技巧》由會員上傳分享,免費在線閱讀,更多相關內容在工程資料-天天文庫。
1、javascript從作用域鏈談閉包神馬是閉包關于閉包的概念,是婆說婆有理。閉包是指冇權訪問另外一個函數作用域中的變量的函數這概念有點繞,拆分一2從概念上說,閉包有兩個特點:?1、函數?2、能訪問另外一個函數作用域中的變量在ES6之前,Javascript只有函數作用域的概念,沒有塊級作用域(但calch捕獲的異常只能在catch塊中訪問)的概念(IIFE叮以創(chuàng)建局部作用域)。每個函數作用域都是封閉的,即外部是訪問不到函數作用域小的變量。functiongetName(){varname=〃美女的名字〃;conso
2、le,log(name);//〃美女的名字〃}functiondisplayName(){console,log(name);//扌艮錯}但是為了得到美女的名字,不死心的單身汪把代碼改成了這樣:functiongetName(){varname=〃美女的名字〃;funcliondisplayNameO{console?log(name);}returndisplayName;}var美女二getName();美女()//〃美女的名字〃這下,美女是一個閉包了,單身汪想怎么玩就怎么玩了。(但并不推薦單身汪用屮文做變量名
3、的寫法,大家不要學)。關于閉包呢,還想再說三點:1、閉包可以訪問當前函數以外的變量functiongetOuter(){vardate='815,;functiongetDate(str){console.log(str+date);//訪問外部的date}returngetDate(J今天是://"今天是:815〃}getOuter();getDate是一個閉包,該函數執(zhí)行時,會形成一個作用域A,A中并沒有定義變量date,但它能在父一?級作用域小找到該變量的定義。2、即使外部函數已經返回,閉包仍能訪問外部函數定
4、義的變量functiongetOuter(){vardate二'815';functiongetDate(str){console.log(str+date);//訪問外部的date}returngetDate;//外部函數返冋}vartoday二getOuter();todayC今天是://〃今天是:815〃today(J明天不是:’);//"明天不是:815〃3、閉包可以更新外部變量的值functionupdateCount(){varcount=0;functiongetCount(val){count=va
5、l;console,log(count);}returngctCount;//外部函數返回}varcount=updateCount();count(815);//815count(816);//816作用域鏈為毛閉包就能訪問外部函數的變量呢?這就要說說Javascript屮的作用域鏈To__Javascript屮有一個執(zhí)行環(huán)境(executioncontext)的概念,它定義了變量或函數冇權訪問的其它數據,決定了他們各自的行為。每個執(zhí)行環(huán)境都冇一個與Z關聯(lián)的變量對彖,環(huán)境中定義的所有變量和函數都保存在這個對象中。
6、你可以把它當做Javascript的一個普通對象,但是你只能修改它的屬性,卻不能引用它。變量對象也是有父作用域的。當訪問一個變量時,解釋器會首先在當前作用域查找標示符,如果沒有找到,就去父作用域找,直到找到該變量的標示符或者不再存在父作用域了,這就是作用域鏈。作用域鏈和原型繼承有點類似,但乂有點小區(qū)別:如果去查找一個普通對象的屬性吋,在當前對象和其原型屮都找不到時,會返冋undefined;但查找的屬性在作用域鏈中不存在的話就會拋出ReferenceError0作用域鏈的頂端是全局對象。對于全局環(huán)境中的代碼,作用域
7、鏈只包含一個元索:全局對象。所以,在全局環(huán)境中定義變量的時候,它們就會被定義到全局對象中。當函數被調用的時候,作用域鏈就會包含多個作用域對象。?全局環(huán)境關于作用域鏈講得略多(紅皮書上有關于作用域及執(zhí)行環(huán)境的詳細解釋),看一個簡單地例子://my_script?js"usestrict";varfoo二1;varbar二2;在全局環(huán)境小,創(chuàng)建了兩個簡單地變量。如前而所說,此時變量對象是全局對象。?Non-nestedfunctions改動一下代碼,創(chuàng)建一個沒有函數嵌套的函數:〃usestrict";varfoo=1;
8、varbar=2;functionmyFunc(){//--define1ocal-to-functionvariablesvara=1;varb=2;varfoo=3;console.log(/zinsidemyFunc〃);}console.log(〃outside〃);//--andthen,callit:myFunc();當myFunc被定義的時候,