var let const 定義方式比較
Node.js var let const 定義方式比較
Categories:
定義方式
定義方式 | 說明 |
---|---|
const | 不會被重新指定值的變數 e.g. const PI = 3.14159 |
let | 在指定區塊才有效用的變數 |
var | 在整個函式或區塊中皆可以取用 |
var
在 function 外的 var 可以被 function 取用
var my_name = "KJ";
function sayMyName() {
// KJ
console.log(my_name);
}
sayMyName();
在 function 內的 var 無法被外面取用
function defineMyName() {
var my_name = "KJ";
}
// my_name is not defined
console.log(my_name);
同樣變數 可以
重新定義
不建議使用,會導致變數定義混亂
var my_name = "Kay";
var my_name = "Jay";
// Jay
console.log(my_name);
let
在 function 內的 let 無法被外面取用
function defineMyName() {
let my_name = "KJ";
}
// my_name is not defined
console.log(my_name);
內部變數與外部變數名稱一樣不會互相污染
let my_name = "Kay";
if (true) {
let my_name = "Jay";
// Jay
console.log(my_name);
}
// Kay
console.log(my_name);
同樣變數無法重新定義
let my_name = "Kay";
// SyntaxError: Identifier 'my_name' has already been declared
let my_name = "Jay";
const
常數無法重新被賦予值
const my_name = "Kay";
my_name = "Jay";
// TypeError: Assignment to constant variable.
console.log(my_name);
const employee = {
name: "Kay",
age: 18
};
// TypeError: Assignment to constant variable.
employee = {
name: "Jay",
age: 17
}
常數物件數值可以被異動
const employee = {
name: "Kay",
age: 18
};
// { name: 'Kay', age: 18 }
console.log(employee);
// 變更常數物件數值
employee.name = "Jay";
employee.age = 17;
// { name: 'Jay', age: 17 }
console.log(employee);
同樣變數無法重新定義
const my_name = "Kay";
// SyntaxError: Identifier 'my_name' has already been declared
const my_name = "Jay";
必須賦予初始值
// SyntaxError: Missing initializer in const declaration
const my_name;
var vs let vs const
類型 | var | let | const |
---|---|---|---|
scope 範圍 | global 全域 | block 區塊 | block 區塊 |
re-declared 重新定義 | 可 | X | X |
update 更新 | 可 | 可 | X |
賦予初始值 | 不限制 | 不限制 | 必要 |
function run() {
var my_name = "Kay";
let my_age = 19;
// Kay 19
console.log(my_name, my_age);
{
var their_name = "Jay"
let their_age = 17;
// Jay 17
console.log(their_name, their_age);
}
// Jay
console.log(their_name);
// ReferenceError: their_age is not defined
console.log(their_age);
}
run();
賦予值異動
var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My var value: " + i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
// My var value: 3
// My var value: 3
// My var value: 3
var i
最後已經變成 3 了,所以最後會印出三行 My var value: 3
var funcs = [];
// let's create 3 functions
for (let i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My let value: " + i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
// My let value: 0
// My let value: 1
// My let value: 2
let i
只作用在 for 的 scope 中,所以最後會分別印他們當初傳進去的值
經典問題
Scope 數值
var a = 1;
var b = 1;
var e = 1;
function test(a) {
// undefined
console.log(a);
var b = 2;
// 2
console.log(b);
if (true) {
let c = 5;
var d = 6;
const e = 7;
}
// undefined
console.log(c);
// 6
console.log(d);
// 1
console.log(e);
}
test();
i
執行到後面已經變成 6 了,然後接下來會執行 setTimeout
的程式,印出來的變數都是 6
for(var i = 1; i <= 5; i++) {
setTimeout(function() {
console.log(i)
}, 0)
}
// 6
// 6
// 6
// 6
// 6
解決方式
使用 let
將變數定在 block 中,區塊中會保留原本的數值
// 方法 1
for(let i = 1; i <= 5; i++) {
setTimeout(function() { console.log(i) }, 0)
}
// 1
// 2
// 3
// 4
// 5
使用 IIFE 方式,事先將要處理的變數傳入會立即執行的函式,將變數包在 block 中,這樣執行的時候也可以拿到正確的值
// 方法 2 IIFE
for(var i = 1; i <= 5; i++) {
(function (x) {
setTimeout(function() { console.log(x) }, 0)
})(i)
}
// 1
// 2
// 3
// 4
// 5