Pages - Menu

2016年7月5日 星期二

[程式開發] Javascript let 與 var 差別 筆記

先來看看MDN對兩者的定義

var
Declares a variable, optionally initializing it to a value.
 let
Declares a block scope local variable, optionally initializing it to a value.
差別在於 let 特別用在block scope

以下範例 清楚解釋 block scope 概念 : var可以作用在該scope以內的所有scope ,但是let 只作用在該block scope
var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // the scope is global
  let b = 22; // the scope is inside the if-block

  console.log(a);  // 11
  console.log(b);  // 22
} 

console.log(a); // 11
console.log(b); // 2
另一個範例,可以看出var作用域變數內都會是同一個,而 let 只作用該scope 所以裡面的不一樣
function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}
!!!有些 let 需要注意的事情

(1) 同一個Scope不能重複 let 宣告相同變數
if (x) {
  let foo;
  let foo; // SyntaxError thrown.
}
下面也是相同狀況
switch (x) {
  case 0:
    let foo;
    break;
    
  case 1:
    let foo; // SyntaxError for redeclaration.
    break;
}

(2) 在最外層(Top level , Global) 不能用 let 宣告
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

用let的好處

(1) 每一個 instance 是分開不一樣的 不像 var 只會呈現最後數值
var list = document.getElementById("list");

for (let i = 1; i <= 5; i++) {
  let item = document.createElement("li");
  item.appendChild(document.createTextNode("Item " + i));

  item.onclick = function (ev) {
    console.log("Item " + i + " is clicked.");
  };
  list.appendChild(item);
}
如果用var是不行的,結果會是 var 都是 6

參考: MDN

另外補充

(1) Var 如果再最外層(Top level) 其實就是全域變數

(2) 如果沒有任何宣告就使用變數,他則會被當成全域變數 而且可以delete
x = 42;
var y = 43;
myobj = new Number();
myobj.h = 4;    // create property h
delete x;       // returns true (can delete if declared implicitly)
delete y;       // returns false (cannot delete if declared with var)
delete Math.PI; // returns false (cannot delete predefined properties)
delete myobj.h; // returns true (can delete user-defined properties)
delete myobj;   // returns true (can delete if declared implicitly)

(3) hoisting: 在js 裡面 所有var宣告的都會被提升到最前面先宣告初始化

比如說,原本你這樣打
/**
 * Example 1
 */
console.log(x === undefined); // true
var x = 3;

/**
 * Example 2
 */
// will return a value of undefined
var myvar = "my value";
 
(function() {
  console.log(myvar); // undefined
  var myvar = "local value";
})();
則他在執行時會這樣做:
/**
 * Example 1
 */
var x;
console.log(x === undefined); // true
x = 3;
 
/**
 * Example 2
 */
var myvar = "my value";
 
(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = "local value";
})();
而 let 則是沒有這個特性 所以他會直接是錯的
console.log(x); // ReferenceError
let x = 3;
另外function 宣告也有這個特性 (function 附值則沒有)
/* Function declaration */

foo(); // "bar"

function foo() {
  console.log("bar");
}


/* Function expression */

baz(); // ReferenceError: baz is not a function(it's undefined!!!)

var baz = function() {
  console.log("bar2");
};
function 若是沒有return值 typeof 會是undefined 若有 typeof 則看return 是什麼型態。












1 則留言: