2013-02-21 33 views
2

在書Secrets of the JavaScript Ninja,p。 43 - 46,它有一個像一些代碼:在JavaScript中,當局部變量被提起時,甚至在它被聲明之前它是否在範圍內?

function assert(flag, msg) { 
    if (!flag) { 
     console.log("Assertion failed for: " + msg); 
    } 
} 

function outer() { 
    var a = 1; 

    function inner() { } 

    assert(typeof b === "number", "b is in scope"); 
    var b = 1; 
} 

outer(); 

而得出的結論是,因爲斷言失敗,即「B不在範圍內還沒有,直到它被宣佈」。但我認爲這是另外的,因爲首先,b已經可以具有本地範圍,但僅僅是它不是「數字」。實際上b已經是本地範圍b,並且會影響任何全局b

例如:

var b = 123; 

function foo() { 
    b = 456; 

    var b = 789; 
} 

foo(); 

console.log(b); // prints out 123 

因爲它打印出123,所以我們可以看到,在執行線b = 456;時,b已經是本地範圍b。 (即使在任務尚未初始化之前)。

另外,我們可以把它打印出來,而不是分配給b:如此反覆

var b = 123; 

function foo() { 
    console.log(b); // prints out undefined 

    var b = 789; 
} 

foo(); 

console.log(b);  // prints out 123 

,我們可以看出,首次印出不是123undefined,這意味着b是局部範圍b ,因此,b確實已經在書中的範圍內。

上述說明和概念是否正確?

+0

'var b'被懸掛在函數作用域的頂部,所以後面的'b'在函數中引用本地'b',而不管順序如何。 – Blender 2013-02-21 08:06:08

+0

那麼這本書的描述是錯誤的?你是什​​麼意思「功能範圍的頂部」?(範圍是範圍,沒有範圍的頂部或底部)。你的意思是「懸掛在函數的頂部(就像它是第一行一樣,並且在函數的本地範圍內,而不管它在函數內部出現的位置嗎?」) – 2013-02-21 08:08:56

+1

我不喜歡術語「提升」,它表示聲明是移到了某個東西的頂端,這並不是實際發生的事情,標準解釋了它(http://ecma-international.org/ecma-262/5.1/#sec-10.4),因爲所有的聲明都是在之前處理的任何代碼都會被執行,所以這也是你應該考慮的問題,對範圍的影響是副作用 – RobG 2013-02-21 08:25:01

回答

5

確實,這本書的結論是錯誤的。 var b任何地方裏面功能意味着b存在任何地方裏面的功能。這就是「提升」的意思。所有varfunction聲明都被提升到最高位置,而不管它們在範圍內發生了什麼。 尚未被分配。

2

關於代碼:

assert(typeof b === "number", "b is in scope"); 
var b = 1; 

聲明:

「B不在範圍內還沒有,直到它被宣佈爲」

是錯誤的。 b在'範圍內'(因爲它是聲明的,它是在任何代碼執行之前創建的),但尚未分配一個值,所以typeof b返回undefined並且測試失敗。

以上描述和概念是否正確?

是的,或多或少。一個更簡單的證明是:

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

function bar() { 
    alert(x); 
    x = 5; 
} 

foo() // 'undefined' since b is "in scope" but hasn't been assigned a value yet 

bar() // throws an error since x isn't "in scope" until the following line. 
+0

你是什麼意思「或多或少」?如果某些觀點不正確,你能否請求指出它? – 2013-02-21 09:24:38

+0

我說「更多 - 或 - 樂ss「,因爲」範圍內「是行話。嚴格地說,在執行任何代碼之前,聲明局部變量會創建本地執行對象的屬性。標識符解析會發現「本地」屬性(變量),而不是在範圍鏈上進一步搜索。沒有提到的是全局'b'在分配給它的代碼導致它被創建之前不存在。最後,一旦作爲全局創建,即使它可能被作用域鏈的其他部分中具有相同名稱的變量「隱藏起來」,也會從同一個全局上下文創建的每個執行上下文處於「範圍內」。 – RobG 2013-02-21 23:26:00

相關問題