[Javascript] var關鍵字的用途是什麼,什麼時候應該使用它(或省略它)?



Answers

有一個區別

var x = 1在當前作用域(又名執行上下文)中聲明變量 x 。 如果聲明出現在函數中 - 聲明了局部變量; 如果它在全局範圍內 - 則聲明一個全局變量。

另一方面, x = 1僅僅是財產分配。 它首先試圖根據作用域鏈來解析x 。 如果它在該範圍鏈中的任何地方找到它,它將執行分配; 如果它沒有找到x ,那麼只會在全局對象 (這是作用域鏈中的頂級對象) 上創建x屬性

現在註意它沒有聲明一個全局變量,它創建了一個全局屬性。

兩者之間的區別很微妙,除非您明白變量聲明也創建屬性 (僅在變量對像上),並且Javascript中的每個屬性(以及ECMAScript)都具有描述其屬性的特定標誌 - ReadOnly,DontEnum和DontDelete。

由於變量聲明使用DontDelete標誌創建屬性,因此var x = 1x = 1 (在全局範圍中執行時)之間的區別在於前一個 - 變量聲明 - 創建DontDelete'able屬性,而後一個不。 因此,通過此隱式賦值創建的屬性可以從全局對像中刪除,而前一個 - 通過變量聲明創建的屬性 - 不能刪除。

但是,這當然只是理論, 實際上由於實現中的各種錯誤(例如來自IE的錯誤), 兩者之間還有更多的差異

希望這一切都有道理:)

[2010/12/16更新]

在ES5(ECMAScript 5;最近標準化,第5版的語言)中,有一個所謂的“嚴格模式” - 一種選擇語言模式,它略微改變了未聲明的作業行為。 在嚴格模式下,分配給未聲明的標識符是一個ReferenceError 。 其理由是要抓住意外的任務,防止產生不希望的全球性質。 一些較新的瀏覽器已經開始支持嚴格模式。 例如,參見我的compat表

Question

注意 :這個問題是從ECMAScript版本3或5的角度提出的。在ECMAScript 6發行版中引入新功能後,答案可能會過時。

JavaScript中var關鍵字的功能究竟是什麼,以及它們之間的區別是什麼

var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;

someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;

你什麼時候可以使用任何一個,為什麼?它有什麼作用?




沒有var - 全局變量。

強烈建議總是使用var語句,因為本地環境中的init全局變量 - 是邪惡的。 但是,如果你需要這個骯髒的竅門,你應該在頁面開始寫評論:

/* global: varname1, varname2... */



下面是一個很好的例子,說明如何從var聲明局部變量:

<script>
one();

function one()
{
    for (i = 0;i < 10;i++)
    {
        two();
        alert(i);
    }
}

function two()
{
    i = 1;
}
</script>

i在循環的每次迭代時重置,因為它不是在for循環中本地聲明的for而是全局的)最終導致無限循環




@Chris S給出了一個很好的例子,展示了var和no var之間的實際區別(和危險)。 這裡有另外一個,我覺得這個特別危險,因為只有在異步環境中才可以看到差異,所以在測試過程中它很容易滑倒。

正如你所期望的,以下代碼段輸出["text"]

function var_fun() {
  let array = []
  array.push('text')
  return array
}

console.log(var_fun())

那麼下面的代碼片段(注意在array之前丟失):

function var_fun() {
  array = []
  array.push('text')
  return array
}

console.log(var_fun())

異步執行數據操作仍然會產生與單個執行程序相同的結果:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

var_fun().then(result => {console.log(result)})

但是與多個行為有所不同:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})

然而,使用讓:

function var_fun() {
  let array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})




我發現當聲明帶或不帶var的變量以及函數內部或外部時,人們會感到困惑。 以下是一個深刻的例子,它將引導您完成以下步驟:

在jsfiddle中查看下面的腳本

a = 1;// Defined outside the function without var
var b = 1;// Defined outside the function with var
alert("Starting outside of all functions... \n \n a, b defined but c, d not defined yet: \n a:" + a + "\n b:" + b + "\n \n (If I try to show the value of the undefined c or d, console.log would throw 'Uncaught ReferenceError: c is not defined' error and script would stop running!)");

function testVar1(){
    c = 1;// Defined inside the function without var
    var d = 1;// Defined inside the function with var
    alert("Now inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};


testVar1();
alert("Run the 1. function again...");
testVar1();

function testVar2(){
    var d = 1;// Defined inside the function with var
    alert("Now inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};

testVar2();

alert("Now outside of all functions... \n \n Final Values: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n You will not be able to see d here because then the value is requested, console.log would throw error 'Uncaught ReferenceError: d is not defined' and script would stop. \n ");
alert("**************\n Conclusion \n ************** \n \n 1. No matter declared with or without var (like a, b) if they get their value outside the function, they will preserve their value and also any other values that are added inside various functions through the script are preserved.\n 2. If the variable is declared without var inside a function (like c), it will act like the previous rule, it will preserve its value across all functions from now on. Either it got its first value in function testVar1() it still preserves the value and get additional value in function testVar2() \n 3. If the variable is declared with var inside a function only (like d in testVar1 or testVar2) it will will be undefined whenever the function ends. So it will be temporary variable in a function.");
alert("Now check console.log for the error when value d is requested next:");
alert(d);

結論

  1. 無論是否使用var聲明(如a,b),如果它們在函數外獲得它們的值,它們將保留它們的值,並且通過腳本保存在各個函數內部添加的任何其他值。
  2. 如果變量在函數內部沒有var聲明(如c),它將像前一個規則一樣工作,它將從現在開始保留所有函數的值。 要么它在函數testVar1()中獲得其第一個值,它仍然保留該值並在函數testVar2()中獲得附加值
  3. 如果變量只在一個函數中聲明為var(比如testVar1或testVar2中的d),那麼函數結束時它將不確定。 所以它將是一個函數中的臨時變量。



不使用“var”變量只能在設置值時進行定義。 例如:

my_var;

無法在全球範圍任何其他範圍內工作 。 它應該具有以下價值:

my_var = "value";

另一方面,你可以定義一個可變的像;

var my_var;

它的值是undefined (它的值不是null ,它不等於null有趣)。




這是我為你理解這個概念而編寫的示例代碼:

var foo = 5; 
bar = 2;     
fooba = 3;

// Execute an anonymous function
(function() {    
    bar = 100;             //overwrites global scope bar
    var foo = 4;           //a new foo variable is created in this' function's scope
    var fooba = 900;       //same as above
    document.write(foo);   //prints 4
    document.write(bar);   //prints 100
    document.write(fooba); //prints 900
})();

document.write('<br/>');
document.write('<br/>');
document.write(foo);       //prints 5
document.write(bar);       //prints 100
document.write(fooba);     //prints 3



當Javascript在瀏覽器中執行時,您的所有代碼都被一個with語句包圍,如下所示:

with (window) {
    //Your code
}

有關- MDN的更多信息

由於var 在當前範圍內聲明了一個變量,因此在窗口內聲明var並且根本不聲明它是沒有區別的。

當你不是直接進入窗口時,例如在一個函數內部或者在一個塊內部,就會產生差異。

使用var可以隱藏具有相同名稱的外部變量。 用這種方法你可以模擬一個“私人”變量,但這是另一個話題。

經驗法則是始終使用var ,因為否則會冒著引入細微錯誤的風險。

編輯:我收到的批評後,我想強調以下幾點:

  • var 在當前作用域中聲明一個變量
  • 全球範圍是window
  • 不使用var隱式地在全局範圍(窗口)中聲明var
  • 使用var在全局範圍(窗口)中聲明變量與刪除變量相同。
  • 使用var聲明與窗口不同的範圍變量與聲明沒有var的變量不同
  • 總是明確聲明var因為這是一個好習慣



另一個差異例如

var a = a || [] ; // works 

a = a || [] ; // a is undefined error.



Links