作用域
不了解作用域的倔友,可以移步你不知道的js作用域
-
var-
var在函数作用域内有效,并且能在函数外被访问(如果定义在全局作用域)。 -
例如:
-
function testVar() {
var a = 1;
if (true) {
var b = 2;
}
console.log(a); // 1
console.log(b); // 2,在函数内任何地方都可访问到 b
}
testVar();
console.log(a); // 报错,a is not defined,在函数外无法直接访问到 a,但如果 a 定义在全局作用域则可以被访问
-
let和const-
在块级作用域(如花括号内)有效。
-
例如:
-
function testLetConst() {
let c = 3;
const d = 4;
if (true) {
let e = 5;
const f = 6;
}
console.log(c); // 3
// console.log(e); // 报错,e is not defined,在外部无法访问块级作用域内的 e
// console.log(f); // 报错,f is not defined,在外部无法访问块级作用域内的 f
}
testLetConst();
重新赋值与重新声明
-
var-
可以重新赋值和重新声明。
-
例如:
-
var g = 7;
var g = 8;
console.log(g); // 8
-
let-
可以重新赋值但不能重新声明。
-
例如:
-
let h = 9;
h = 10;
// let h = 11; // 报错,Identifier 'h' has already been declared
console.log(h); // 10
-
const-
既不能重新赋值,也不能重新声明。定义时必须初始化。
-
例如:
-
const i = 12;
// i = 13; // 报错,Assignment to constant variable.
// const i = 14; // 报错,Identifier 'i' has already been declared
提升(Hoisting)
-
var-
会被提升到其作用域的顶部,但不会初始化。
-
例如:
-
console.log(j); // undefined
var j = 15;
-
let和const-
也会被提升到作用域的顶部,但在初始化之前不能被访问(称为 “暂时性死区”)。
-
例如:
-
console.log(k); // 报错,ReferenceError: Cannot access 'k' before initialization
let k = 16;
全局对象属性
-
var-
在全局作用域下,用
var声明的变量会成为全局对象的属性。例如,在浏览器环境中,var声明的变量会成为window对象的属性。 -
例如:
-
var l = 17;
console.log(window.l); // 17
-
let和const-
不会成为全局对象的属性。
-
例如:
-
let m = 18;
const n = 19;
console.log(window.m); // undefined
console.log(window.n); // undefined
块级作用域与变量泄漏
-
var-
在
for循环中使用var,循环变量会在全局或函数作用域内共享,可能导致意外错误。 -
例如:
-
for (var o = 0; o < 3; o++) {
setTimeout(function() {
console.log(o); // 最终会输出 3 三次,因为循环结束后 o 的值为 3
}, 100);
}
-
let-
使用
let可以确保每次迭代都有一个新的绑定,解决了上述问题。 -
例如:
-
for (let p = 0; p < 3; p++) {
setTimeout(function() {
console.log(p); // 分别输出 0、1、2,每次迭代都有新的绑定
}, 100);
}
暂时性死区
-
let和const-
暂时性死区是指在变量声明之前访问变量会导致引用错误。
-
例如:
-
let q;
// console.log(q); // 报错,ReferenceError: Cannot access 'q' before initialization
q = 20;
console.log(q); // 20
-
对于
const也是同样的情况:
const r; // 报错,Missing initializer in const declaration
最佳实践
-
const-
使用
const声明那些不会改变的变量是个好习惯,可以强调代码的不可变性。 -
例如:
-
const PI = 3.14159;
// PI = 3.14; // 报错,Assignment to constant variable.
-
let-
只有在明确需要重新赋值的情况下使用
let。 -
例如:
-
let count = 0;
for (let i = 0; i < 10; i++) {
count++;
}
console.log(count); // 10
-
避免使用
var-
在现代 JavaScript 编程中,几乎不会再用到
var了,因为let和const能更好地处理作用域和提升问题。
-
let和const在 JavaScript 中提供了更安全、更清晰的变量定义方式,有助于避免一些常见的编程错误,提高代码的可读性和可维护性。