var,let,还是 const?
var,let,还是 const?
原文:https://medium.com/hackernoon/js-var-let-or-const-67e51dbb716f
ES6 简介
你必须理解var才能领会let / const的好处。让我们倒回去。
复习:变量声明
有意识地在特定的范围内声明变量,使用var声明,以保持代码的清晰和可维护性,这一点很重要。
var x = "outside";
function foo() {
var x = "inside";
console.log(x);
}foo(); // inside
console.log(x); // outside
上面的代码使用var在函数内外正确地声明了x。foo里没有var会怎么样?
var x = "outside";
function foo() {
x = "inside";
console.log(x);
}foo(); // inside
console.log(x); // inside
啊哦!函数外的x被函数内的x覆盖了,因为我们没有指定x的作用域仅限于foo!
吊装最佳实践
在当前作用域的顶部使用var声明变量。
好的:
console.log('sup')
var i = 0;
更好:
var i = 0;
console.log('sup')
复习:吊装
使用var声明的变量总是被提升到它们的范围的顶部。
console.log(j); // ReferenceError: j is not definedconsole.log(i); // undefined
var i = 0;
变量 j从未被声明为,所以我们得到一个错误消息“我从未听说过j!”。
i 因吊装而在测井前 申报。解释器是这样执行的:
var i;
console.log(i);
i = 0;
解释器将变量声明移动到作用域的顶部。
但是,变量还没有 赋值给0。undefined说“我知道i 存在,但是我不知道i 指向什么值,因为你没有把赋值给任何东西”。
补充 1:如果 *var* 指的是一个函数 怎么办?
补充 2:提升并不会在物理上“移动”你的代码— MDN
功能范围
var是函数作用域 : 作用域限于定义它的函数。
function foo() {
var i = 0;
}console.log(i); // ReferenceError: i is not defined
i只存在于foo中,所以我们得到一个错误:“我从未听说过i!”。
块范围
var是而不是 块范围的:范围是而不是局限于定义它的块。
var i = 0
if (true) {
var i = 1;
}console.log(i); // 1
i是否仍在内的“全局范围”内阻塞。i的值被覆盖,这可能不是本意。

让
let变量是 块范围的!具体范围=错误少。
*let i = 0;
if (true) {
let i = 1;
}console.log(i); // 0*
即使i在 if 块中被赋值到1,那个赋值是 local 到块,因此我们的【全局】i仍然是0。if块的作用域独立于全局作用域。
const ==常数
const限制重写变量。
*const i = 0;
i = 1; // TypeError: Assignment to constant variable.*
const甚至不允许你声明一个没有赋值(常量)的变量!
*const i; // SyntaxError: Missing initializer in const declaration*
const和let一样,是块作用域。
*if (true) {
const i = 0;
}console.log(i); // ReferenceError: i is not defined*
const是否允许变量 突变(JS 中只有对象/数组是可变的)。**
数组突变:
****const a = [1];
const b = a;
console.log(a === b); // true
b.push(2);
console.log(a === b); // true
console.log(a); /// [ 1, 2 ]****
对象突变:
****const obj = {};
obj.i = 1;
console.log(obj); // { i: 1 }****
左/const 提升
let和const申报是而不是吊装!
编辑:技术上来说它们被吊起,但是它们没有被初始化为任何东西(
var被初始化为undefined)。
****console.log(a); // undefined
var a = 2;console.log(b); // Uncaught ReferenceError: b is not definedconsole.log(c); // Uncaught ReferenceError: c is not defined
let c = 2;****
这可以防止变量声明放在变量引用之后。
isEqualTo5有一个 bug——它总是返回true。
****function isEqualTo5(n) {
return !(n - five);
var five = 5;
}
console.log(isEqualTo5(4)); // true****
问题是five直到被引用后才被赋值。它是声明的,所以当它在 return 语句中被引用时,它的值是undefined。
****!(4 - undefined) === !(NaN) === true****
这个 bug 可能很难抓到。let / const来救援了!
****function isEqualTo5(n) {
return !(n - five);
const five = 5;
}
console.log(isEqualTo5(4)); // ReferenceError: five is not defined****
const不提升声明→错误:声明前引用→防止 bug。
特定范围=更少的错误+更好的可读性/可维护性。