最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

容易被忽略的JS腳本特性

 更新時(shí)間:2011年09月13日 22:02:55   作者:  
容易被忽略的JS腳本特性,學(xué)習(xí)js的朋友可以參考下。
一、容易被忽略的局部變量
復(fù)制代碼 代碼如下:

var a = 5;
(function(){
alert(a);
var a = a ++;
alert(a);
})()
alert(a);

思考這段代碼的執(zhí)行結(jié)果。
執(zhí)行后,看看是否和你想象的一致?
ok,這段代碼里核心的知識(shí)點(diǎn)是 var a = a++,其中兩個(gè)變量 a 都是匿名函數(shù)內(nèi)部的局部變量,是同一個(gè),和全局變量 a 是不一樣的。
為什么?我們來(lái)看看ECMA規(guī)范對(duì)變量聲明語(yǔ)句的定義:
復(fù)制代碼 代碼如下:

Description
If the variable statement occurs inside a FunctionDeclaration, the
variables are defined with function-local scope in that function, as
described in s10.1.3. Otherwise, they are defined with global scope
(that is, they are created as members of the global object, as described
in 10.1.3) using property attributes { DontDelete }. Variables are
created when the execution scope is entered. A Block does not define a new
execution scope. Only Program and FunctionDeclaration produce a new
scope. Variables are initialised to undefined when created. A variable with
an Initialiser is assigned the value of its AssignmentExpression when the
VariableStatement is executed, not when the variable is created.

聲明中提到:進(jìn)入作用域環(huán)境后,變量就會(huì)被創(chuàng)建,并賦予初始值undefined。在變量聲明語(yǔ)句執(zhí)行時(shí)才會(huì)把賦值表達(dá)式的值指派給該變量,而并不是在該變量被創(chuàng)建時(shí)。
因此上面的代碼可以等價(jià)于:
復(fù)制代碼 代碼如下:

var a;
a = 5;
(function(){
var a;
alert(a);
a = a ++;
alert(a);
})()
alert(a);

這樣應(yīng)該會(huì)更容易理解了。
二、容易被忽略的全局變量
復(fù)制代碼 代碼如下:

(function(){
var a = b = 5;
})()
alert(b);

這是玉伯幾天前分享到的知識(shí)點(diǎn),蠻有意義的,在此也做個(gè)分析。
首先,考慮執(zhí)行結(jié)果為什么是:5。
ok,原因出在 var a = b = 5 這句。
為深入分析這個(gè)語(yǔ)句,我們繼續(xù)要參照ECMA規(guī)范對(duì)聲明語(yǔ)句的定義:
var a = b = 5;等同為 var a; a = b = 5;兩條語(yǔ)句,后者是賦值表達(dá)式,其在ECMA中的定義是這樣的:
復(fù)制代碼 代碼如下:

Simple Assignment ( = )
The production AssignmentExpression : LeftHandSideExpression =
AssignmentExpression is evaluated as follows:
1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3. Call GetValue(Result(2)).
4. Call PutValue(Result(1), Result(3)).
5. Return Result(3).

對(duì)于a = b = 5;先執(zhí)行左邊表達(dá)式 a,這是一個(gè)標(biāo)識(shí)符表達(dá)式,根據(jù)規(guī)范第 10.1.4,其執(zhí)行方式如下:
復(fù)制代碼 代碼如下:

During execution, the syntactic production PrimaryExpression : Identifier
is evaluated using the following algorithm:
1. Get the next object in the scope chain. If there isn't one, go to step 5.
2. Call the [[HasProperty]] method of Result(1), passing the Identifier as
the property.
3. If Result(2) is true, return a value of type Reference whose base
object is Result(1) and whose property name is the Identifier.
4. Go to step 1.
5. Return a value of type Reference whose base object is null and whose
property name is the Identifier.

搜尋作用域鏈,找到最近的一個(gè) a 的引用,很明顯,在匿名函數(shù)內(nèi)部作用域就可以找到,于是變量 a 確定下來(lái)。
接著再執(zhí)行右邊的表達(dá)式 b = 5 ,還是一個(gè)賦值表達(dá)式,重復(fù)賦值規(guī)則第一步,因?yàn)樽兞?b 在匿名函數(shù)環(huán)境內(nèi)未聲明過(guò),所以接著去 window 全局環(huán)境下去找 window.b ,被隱式聲明為全局變量,最后賦值為 5,根據(jù)規(guī)則第五步,表達(dá)式的結(jié)果也會(huì)再賦值給 a。最終達(dá)到 a 和 b 都為 5 ,區(qū)別是 a 是局部變量,而 b 是全局變量。
我們?cè)賮?lái)理一下 (function(){var a = b = 5})() 表達(dá)式內(nèi)部整體的執(zhí)行順序:
1.匿名函數(shù)內(nèi)創(chuàng)建變量a;
2.賦予初始值undefined;
3.取得變量a的引用; //a
4.取得變量b的引用; //window.b
5.對(duì)數(shù)字5求值;
6.賦值5給b的引用:window.b;
7.返回b = 5的結(jié)果5給a的引用:a;
8.返回a = 5的結(jié)果5;
很明顯,中間的一個(gè)步驟使得變量 b 被聲明為全局變量,明白之后,我們不難找到代碼的優(yōu)化點(diǎn):只需將變量 b 顯式聲明為局部變量:
復(fù)制代碼 代碼如下:

(function(){
var a,b;
a = b = 5;
})()

相關(guān)文章

最新評(píng)論

潍坊市| 社旗县| 城步| 汉川市| 蕲春县| 方城县| 鹤峰县| 长葛市| 芷江| 通江县| 汝城县| 临颍县| 富锦市| 鄂托克旗| 旅游| 苍溪县| 日照市| 定远县| 阿城市| 咸丰县| 威宁| 孟州市| 澜沧| 白水县| 昆明市| 揭东县| 襄樊市| 宁阳县| 涞水县| 东丽区| 广东省| 大名县| 巧家县| 若尔盖县| 邯郸县| 阜康市| 洪雅县| 城市| 分宜县| 蒲城县| 教育|