2010-09-16 63 views
24
alert(myVar1); 
return false; 
var myVar1; 

上面的代碼在IE,FF和Opera中引發錯誤,指出返回語句必須進入函數。但它在Safari和Chrome中正常工作(顯示undefined)。變量提升

上面的代碼已被寫入全局範圍。除了所有的功能。

任何理由?

+10

我很害怕,困惑和有點興趣......你想從幫兇? – 2010-09-16 10:06:45

+2

@Hahsen,我只是想了解各種瀏覽器和JavaScript陷阱可用。這是可變的提升,我試圖瞭解它在全球範圍內的行爲以及返回聲明。儘管當你不在函數定義時不允許返回,但仍然代碼在鉻和safari中工作。我試圖找出原因 – alter 2010-09-16 10:36:47

+0

它可能更容易理解爲變量和聲明*預處理*。聲明不會移動(或「懸掛到頂部」),它們在任何代碼執行之前都會被處理。閱讀ECMA-262§10.3瞭解進入執行環境時會發生什麼,這很容易理解。 – RobG 2011-08-26 03:52:54

回答

23

在JavaScript中的變量被移動到腳本的頂部,然後運行。所以,當你運行它會做

var myVar1; 
alert(myVar1); 
return false; 

這是因爲JavaScript並沒有真正有詞法範圍的真正意義。這就是爲什麼它認爲最好的做法是將所有變量聲明在該區域的頂部,以防止吊裝導致問題。 JSLint會對此抱怨。

這是解釋它http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

回報是無效的好文章。如果你想要做一個真提升例子(從上面的鏈接所)做

var foo = 1; 
function bar() { 
    if (!foo) { 
     var foo = 10; 
    } 
    alert(foo); 
} 
bar(); 

這將提醒10

編輯點評後

下面是我的理解,我已經閱讀在某處,但找不到所有我讀過的資料,所以我願意糾正。

此警報感謝JavaScript JIT的差異。 TraceMonkey(http://ejohn.org/blog/tracemonkey/)我相信會採用JavaScript並做一個快速的靜態分析,然後做JIT,然後嘗試運行它。如果失敗了,那顯然沒有用。

V8沒有做靜態分析和移動到JIT然後運行的東西。它更類似於python。如果您在Chrome中的開發人員控制檯中運行該腳本(在windows中按Ctrl + Shift + j),它將引發錯誤,但也會運行以提醒您。

+1

@Automater Tester,你的代碼是完全正確的,它是一個很好的例子,在JavaScript中提升。但我想知道的是,爲什麼返回沒有在Chrome和Safari瀏覽器中拋出錯誤 – alter 2010-09-16 10:43:51

+0

@alter我已經爲您添加了更多信息。 – AutomatedTester 2010-09-16 16:48:19

+3

「在javaScript中,變量被移到腳本的頂部,然後運行。」實際上,變量*名稱*(而不是賦值/定義)被「提升」到包含範圍的頂部(以最近者爲準;「if」等)在這個意義上不創建「範圍」)。 – strager 2010-09-16 17:07:07

3

這個代碼是沒有意義:

  • var myVar1永遠不會跑去。
  • ,因爲你在一個函數是不是return false;不會返回事

歌劇,IE和FF是正確的一個錯誤,因爲這段代碼確實是無效的,因爲你不能夠返回除非你在功能上。

如果它在Safari和Chrome中起作用,它必須是因爲他們使用的JavaScript引擎已經準備好處理錯誤的代碼。我的猜測是他們會看到「return」,並將其替換爲某種break

有關功能的更多信息:http://www.w3schools.com/js/js_functions.asp

+0

當我在函數外部使用* return *語句時,Chrome出現錯誤。 – 2010-09-16 10:25:35

+3

var myVar1將始終運行,這要歸功於掛起 – AutomatedTester 2010-09-16 10:32:39

+0

,而不管沒有函數返回語句是不允許的,hoising應該發生在這裏,我應該有一個警告說undefined。我沒有看到發生這種情況,當我有一個返回聲明。 – alter 2010-09-16 10:56:30

10

第12節。圖9(第75頁)ECMA-262版本3種狀態:

An ECMAScript program is considered syntactically incorrect if it contains a return statement that is not within a FunctionBody.

也就是說,return外部的功能的是語法錯誤。如果發生語法錯誤,則不運行代碼。想想你作爲例子,如果你寫了:

alert(myVar1); 
return false; 
syntax error)))))))))))))))))); 

此外,第16(第157頁)指出:

An implementation may treat any instance of the following kinds of runtime errors as a syntax error and therefore report it early:

  • Improper uses of return, break, and continue.

Firefox的引擎等。人。 (即那些JavaScript實現,其允許return在全球範圍內)可以是符合,假定以下條款(在相同的部分)允許的return實現定義在全球範圍內:

An implementation shall report all errors as specified, except for the following:

  • An implementation may provide additional types, values, objects, properties, and functions beyond those described in this specification. This may cause constructs (such as looking up a variable in the global scope) to have implementation-defined behaviour instead of throwing an error (such as ReferenceError).
0

它是JavaScript的吊裝的事情,只要換句話說,我們正試圖打印變量,這是不持有任何價值的價值

的Javascript會使上面的代碼爲: -

var myVar1 
 
alert (myVar1) 
 
return false

爲了澄清更多我所指向的鏈接的JavaScript提升:http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

11

有時吊裝可能給出錯誤印象的方式進行了說明,即變量和函數是由JavaScript引擎,如果他們懸掛物理移動之上,這是不實際的權利,通過下面的代碼演示:

console.log(a); 
var a = 'Hello World!'; 

我們看到控制檯undefined,不'Hello World',所以我們得到了BEHA下面的代碼

var a; 
console.log(a); 
a = 'Hello World!'; 

的vior不是

var a = 'Hello World!'; 
console.log(a); 

,你可能會從變量和函數聲明的印象行爲被移動到頂部聲明。

但是JavaScript實際上並沒有在任何地方移動你的代碼。您需要了解JavaScript中的執行上下文。它有兩個階段創建階段和執行階段。在創建階段,爲這些變量和函數創建內存空間,人們似乎將這一步與提升混爲一談。 JavaScript實際上並沒有在任何地方移動代碼,JavaScript會爲所有代碼創建內存空間,即變量和函數,函數可以完全放置在內存中,但在變量的情況下,分配將在執行上下文的執行階段進行處理。因此,當您執行var a = 'Hello World!'時,JavaScript引擎在執行上下文的執行階段開始執行它時知道a的值,因此它將未定義佔位符,並且所有變量最初都設置爲在JavaScript中未定義。所以依靠吊裝和看不明確是不好的。所以在代碼之上聲明變量和函數總是很好的。