2013-06-12 139 views
10

下面的代碼是JavaScript代碼。我正在嘗試理解JavaScript中的函數範圍,並且在here之後的文章之後。我正在複製下面的代碼 -瞭解JavaScript函數範圍

var cow = "purple"; // just a random cow 

var f = function (x) { 
    var r = 0; 
    cow = "glue"; 
    if (x > 3) { 
     var cow = 1; // a local variable 
     r = 7; 
    } 
    return r; 
}; 

var z = f(2); 
alert(cow); // returns purple 

我不太明白爲什麼字符串「紫色」被警告。 cow = "glue";行應該將cow變量的值設置爲「glue」。如果我刪除了if塊,然後在最後一條語句中警告牛,我會看到字符串「glue」被警告。

當f(2)被調用時,if代碼塊沒有被輸入,也沒有任何內容被執行,所以爲什麼我會看到不同的結果?即爲什麼在上一條語句中提醒母牛現在返回字符串「purple」?

回答

4

Javascript沒有塊範圍(catch塊除外)。
所有var語句都是懸掛到包含函數的頂部。

因此,cow引用函數中任何位置的局部變量,即使if從不執行。

+1

實際上,即使'catch'塊都沒有自己的作用域(*變量*環境)。請參閱[爲什麼catch子句有自己的*詞法*環境?](http://stackoverflow.com/q/15034864/1048572) – Bergi

9

函數內部的變量聲明總是被提升到頂部。所以,你的代碼實際上是:

var f = function (x) { 
    var cow, r; 
    r = 0; 
    cow = "glue"; 
    if (x > 3) { 
     cow = 1; // a local variable 
     r = 7; 
    } 
    return r; 
}; 

在函數內部你總是分配給當地cow,從來都不是全球性的。

+0

我認爲你的意思是'var cow,r' there,not'var f, r' –

+0

@ ben336是的,我修復了一段時間。也許你的瀏覽器沒有得到編輯通知? websocket的東西有時會失敗... – bfavaretto

+0

耶現在看到它。今天使用點狀網絡連接。也沒有看到其他人回答,直到我發佈我的。 –

5

這裏要理解的兩件事是,JavaScript變量被提升到其範圍的頂部,並且JavaScript沒有塊範圍。

所以

  1. 在範圍內的所有變量都被認爲在聲明的範圍
  2. 年初if語句不創建一個新的範圍。

所以,你的例子是相當於

var cow = "purple"; // just a random cow 

var f = function (x) { 
    var cow, r = 0; 
    cow = "glue"; 
    if (x > 3) { 
     cow = 1; // a local variable 
     r = 7; 
    } 
    return r; 
}; 

var z = f(2); 
alert(cow); // returns purple 

if語句的VAR聲明提升到頂部。此時,函數中的所有牛引用都指的是局部變量牛,而不是來自外部作用域的牛。

+0

本教程中沒有var前面的cow = glue,我不知道這是否是作者的錯誤 – Ibu

+0

如果要顯示js scope的工作方式,它不一定是錯誤。在if語句中聲明一個var是不好的做法,因爲它很容易混淆,但它並不是「錯誤的」 –

+0

+1,因爲它指出if語句塊沒有創建一個新的作用域,這很可能是OP誤解的來源。 – bfavaretto

4

你沒看過那篇文章,是嗎?它明確規定

是否cow得到變成"glue"當你打電話f(2)?沒有,cow在上面的代碼中是安全的,因爲var cow裏面的if語句聲明適用於整個函數。這意味着cow是整個函數的局部變量。

但是,當您刪除if塊時,還會刪除其中的變量聲明,並且該賦值將以全局變量爲目標。