摘要:文章部分實(shí)例和內(nèi)容來自鳥哥的作用域原理首先應(yīng)該注意幾個(gè)點(diǎn)函數(shù)也是對(duì)象因?yàn)槭窃谌肿饔糜虍?dāng)中當(dāng)執(zhí)行到時(shí)即會(huì)產(chǎn)生在當(dāng)中,函數(shù)的運(yùn)行是在它被定義的作用域當(dāng)中,而非執(zhí)行的作用域當(dāng)中。
文章部分實(shí)例和內(nèi)容來自鳥哥的blogJavascript作用域原理
首先應(yīng)該注意幾個(gè)點(diǎn):
函數(shù)也是對(duì)象
variable object(VO)
A variable object is a container of data associated with the execution context. It’s a special object that stores variables and function declarations defined in the context.
var foo=10; function func(){}; //因?yàn)槭窃谌肿饔糜虍?dāng)中,so... Global VO={ foo:10, func:}
Activation Object(AO)
When a function is activated (called) by the caller, a special object, called an activation object is created.
It’s filled with formal parameters and the special arguments object (which is a map of formal parameters but with index-properties). The activation object then is used as a variable object of the function context.
A function’s variable object is the same simple variable object, but besides variables and function declarations, it also stores formal parameters and arguments object and called the activation object.
function foo(x,y){ var z=30; function bar(){}; } foo(10,20); //當(dāng)執(zhí)行到foo(10,20)時(shí)即會(huì)產(chǎn)生AO Activation Object={ z:30, x:10, y:20, bar:, arguments:{0:10,1:20,length:2} }
Scope Chain(Scope Chain=Activation Object + [[scope]])
A scope chain is a list of objects that are searched for identifiers appear in the code of the context.
在JavaScript當(dāng)中,函數(shù)的運(yùn)行是在它被定義的作用域當(dāng)中,而非執(zhí)行的作用域當(dāng)中。
先看一段代碼:
var name="laurence?"; function show(){ console.log(name); var name="laurence?"; console.log(name); } 最后輸出: undefined laurence? Object={ name1:undefined,//第一個(gè)輸出為undefined,表達(dá)式聲明的局部變量覆蓋全局變量,函數(shù)執(zhí)行到這一語句的時(shí)候才進(jìn)行賦值操作name="laurence?",之前name=undefined name2:"laurence?",//第二個(gè)輸出為"laurence?" } window={ name:"laurence?", show:function() }
注意點(diǎn):
函數(shù)也是對(duì)象
變量提升
函數(shù)在定義過程中,會(huì)將定義時(shí)刻的scope chain鏈接到這個(gè)函數(shù)對(duì)象的[[scope]]屬性上,這個(gè)屬性包含了函數(shù)被創(chuàng)建的作用域中 對(duì)象 的集合,同時(shí)它的作用域會(huì)被創(chuàng)建此函數(shù)的作用域中可訪問的數(shù)據(jù)對(duì)象填充。(對(duì)象的集合、對(duì)象鏈)
函數(shù)的執(zhí)行過程中,會(huì)創(chuàng)建一個(gè) 活動(dòng)對(duì)象 (activation object),該對(duì)象包含了所有的局部變量、命名參數(shù)、參數(shù)集合和this,然后將這個(gè)活動(dòng)對(duì)象作為此時(shí)作用域鏈的最前端,每個(gè)活動(dòng)對(duì)象都有自己的作用域鏈,用于標(biāo)識(shí)符的解析,當(dāng)活動(dòng)對(duì)象被創(chuàng)建時(shí),而它的作用域初始化為當(dāng)前運(yùn)行函數(shù)的[[scope]]所包含的對(duì)象。
var func=function(lps,rps){ var name="XL"; .... } func();
var func=function(){ } 相當(dāng)于匿名函數(shù)的執(zhí)行
(在執(zhí)行函數(shù)創(chuàng)建活動(dòng)對(duì)象(Obj)的過程中,會(huì)創(chuàng)建一個(gè)arguments屬性,然后會(huì)給這個(gè)活動(dòng)對(duì)象添加2個(gè)屬性名,Obj.lps,Obj.rps對(duì)于每一個(gè)在這個(gè)函數(shù)中申明的局部變量和函數(shù)定義,都作為該活動(dòng)對(duì)象的同名屬性,然后將調(diào)用參數(shù)賦值給形參,對(duì)于缺少的調(diào)用參數(shù),賦值為undefined)
//這里func()執(zhí)行時(shí) Obj(AO)={ lps:undefined, rps:undefined, arguments:{} name:"XL" } //創(chuàng)建func()時(shí)為全局對(duì)象: window(Global VO)={ func:function() }
實(shí)際的例子:
function factory(){ var name="laruence"; var intro=function(){ console.log("I"m "+name); } return intro; } function app(para){ var name=para; var func=factory(); func(); } app("eve");
當(dāng)調(diào)用app的時(shí)候,scope chain是由{window活動(dòng)對(duì)象(全局)}+{app活動(dòng)對(duì)象}組成
此時(shí)的[[scope chain]]為( 可訪問的數(shù)據(jù)對(duì)象訪問 ):
[[scope chain]]=[ Active Object={ this:window, arguments:{0:"eve",length:1} name:"eve" func:para:"eve", }, Global VO={ this:window, app: , window:
當(dāng)調(diào)用進(jìn)入factory函數(shù)體內(nèi)時(shí)(注意這里,函數(shù)的scope chain是在它被定義的時(shí)候決定的,而非執(zhí)行的時(shí)候決定的),此時(shí)的factory的scope chain為:
[[scope chain]]={ Active Object={ this:window, arguments:{}, name:"laruence", intro:, }, Global Object(Variable Object)={ this:window, factory: , app: , window: , document: } }
在定義intro函數(shù)的時(shí)候,intro函數(shù)[[scope]]為:
[[scope chain]]={ Object={ name:"laruence", intro:, this: , //注意這里的this指向 arguments:{} }, Gloabal Object={ this:window, factory: , document: , window: } }
從factory函數(shù)返回后,在app體內(nèi)調(diào)用intro時(shí),發(fā)生了標(biāo)識(shí)符的解析,而此時(shí)的scope chain是:
[[scope chain]]={ intro AO={} , Factory AO={ name:"laruence", intro: , }, Global VO={ this:window, factory: , document: , window: } }
在intro執(zhí)行過程中scope chain不包含app活動(dòng)對(duì)象,因此name標(biāo)識(shí)符解析的結(jié)果應(yīng)該是factory活動(dòng)對(duì)象中的name屬性,也就是"laruence"
預(yù)編譯JS在執(zhí)行每段代碼前都會(huì)首先處理var關(guān)鍵字( 函數(shù)定義式 )和function定義式( 函數(shù)聲明式 )
變量提升(hoisting)
1.javascript-the-core(強(qiáng)烈推薦)
2.理解javascript作用域和作用域鏈
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/85909.html
摘要:不是引用類型,無法輸出簡(jiǎn)而言之,堆內(nèi)存存放引用值,棧內(nèi)存存放固定類型值。變量的查詢?cè)谧兞康牟樵冎校L問局部變量要比全局變量來得快,因此不需要向上搜索作用域鏈。 贊助我以寫出更好的文章,give me a cup of coffee? 2017最新最全前端面試題 基本類型值有:undefined,NUll,Boolean,Number和String,這些類型分別在內(nèi)存中占有固定的大小空...
摘要:函數(shù)中的閉包閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。理解閉包預(yù)與變量此時(shí)返回注意觀察下面的輸出內(nèi)容,理解函數(shù)的調(diào)用時(shí)刻和把的賦值給變量時(shí)刻這個(gè)函數(shù)會(huì)返回長(zhǎng)度為的函數(shù)數(shù)組。 Javascript函數(shù)中的閉包 閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。創(chuàng)建閉包的常見方式就是,在一個(gè)函數(shù)的內(nèi)部創(chuàng)建另一個(gè)函數(shù)。 有關(guān)創(chuàng)建作用域鏈以及作用域鏈有什么作用的細(xì)節(jié)對(duì)于徹底理解閉包至關(guān)重...
摘要:環(huán)境由閉包創(chuàng)建時(shí)在作用域中的任何局部變量組成。嚴(yán)格來說,閉包需要滿足三個(gè)條件訪問所在作用域函數(shù)嵌套在所在作用域外被調(diào)用閉包的形成原理先了解的垃圾回收機(jī)制會(huì)找出不再使用的變量,不再使用意味著這個(gè)變量生命周期的結(jié)束。 什么是閉包 最原始定義 閉包(closure),是指函數(shù)變量可以保存在函數(shù)作用域內(nèi),因此看起來是函數(shù)將變量包裹了起來。 //根據(jù)定義,包含變量的函數(shù)就是閉包 function...
摘要:定義函數(shù)的時(shí)候,為什么的值重新從開始了因?yàn)橛忠淮芜\(yùn)行了函數(shù),生成一個(gè)新的的活動(dòng)對(duì)象,所以的作用域鏈引用的是一個(gè)新的值。 前言 在js中,閉包是一個(gè)很重要又相當(dāng)不容易完全理解的要點(diǎn),網(wǎng)上關(guān)于講解閉包的文章非常多,但是并不是非常容易讀懂,在這里以《javascript高級(jí)程序設(shè)計(jì)》里面的理論為基礎(chǔ)。用拆分的方式,深入講解一下對(duì)于閉包的理解,如果有不對(duì)請(qǐng)指正。 寫在閉包之前 閉包的內(nèi)部細(xì)節(jié),...
閱讀 1172·2021-11-24 09:39
閱讀 2675·2021-09-28 09:35
閱讀 1070·2019-08-30 15:55
閱讀 1361·2019-08-30 15:44
閱讀 880·2019-08-29 17:00
閱讀 1969·2019-08-29 12:19
閱讀 3311·2019-08-28 18:28
閱讀 690·2019-08-28 18:10