# 【JS】var, let, const 差異
# JavaScript: var, let, const 差異
# var
若不宣告變數可能不知道變數從哪裡來,造成全域污染,多人開發可能造成問題。
// 為什麼要宣告變數
function fn() {
a = 0; // 全域屬性
}
fn();
console.log(a); // 0
function fnB() {
a = 1;
}
fnB();
console.log(a); // 1
function fn() {
var a = 0; // 作用域在函式裡面
}
fn();
function fnB() {
var a = 1; // 作用域在函式裡面
}
fnB();
console.log(a); // a is not defined
# 全域屬性跟變數的差異
// 屬性可以被刪除
a = 0; // 全域屬性
// 屬性可以被刪除
delete window.a; // a 不見了
var b = 1; // 變數
// 變數無法被刪除
delete window.b; // b 還在
function fn() {
a = 1;
}
fn();
console.log(a);
var 的作用域
var b = 0;
function fn() {
var a = 1;
debugger; // sources > 55行
// local a:1, this > window
// global b:0
}
fn();
var 辭法作用域 var 的作用域在程式碼寫完的當下就確定了
// 基礎
var a = 0;
function fnA() {
console.log(a); // 0
}
function fnB() {
var a = "Raquel";
}
fnB();
fnA();
// 進階
var a = 0;
function fnA() {
console.log(a); // 直接找上面的變數
}
function fnB() {
var a = 1;
fnA(); // 0
}
fnB();
var 的特性
function fn() {
var a = 1;
var a = 0;
}
fn();
{
var b = 2;
}
// not error
console.log(b); // 2
for 迴圈
for (var i = 0; i < 10; i++) {
console.log(i); // 0-9
setTimeout(() => {
console.log(i); // 10*10
}, 0); // setTimeout 往後放
}
console.log(i); // 10
var a;
console.log(a); //undefined 有宣告但沒有賦值
var 的 hoisting 先把所有的程式碼先建立起來,但尚未賦值,所以會先得到 undefined
console.log(a); //undefined (hoisting)
var a = 1;
console.log(a); // 1
# let, const
// let 只存在 {} 內
{
let a = 1;
}
console.log(a); // a is not defined
function fn() {
let a = 1;
}
console.log(a); // a is not defined
for (let i = 0; i < 10; i++) {
console.log(i); // 0-9
setTimeout(() => {
console.log(i); // 0-9
}, 0);
}
console.log(i); // i is not defined
let 跟 var 的差異
- 作用域不同
- let 會出現在 window 內
- 不可重複宣告
var a = 0;
let b = 1;
console.log(window); // 只會有 a, 不會有 b
let 的 hoisting
console.log(a); // error, can't access 'a' before initialization
let a = 0;
function fn(a) {
console.log(a); // 1
var a = 2;
console.log(a); // 2
}
fn(1);
let 類似 hoisting
function fn(a) {
console.log(a); // TDZ 暫時性死區
let a = 2; // Identifier 'a' has already been declared
console.log(a); //
}
fn(1);
# let const 差異
const 無法重新賦值 let 可以重新賦值
物件傳參考(記憶體位置)
const a = {
name: "Ray",
};
a.name = "Raquel"; // ok
const a = {
name: "Ray",
};
// a 指向新的物件
a = {
name: "Raquel", // error
};