总体来说,var
和let
的区别就是作用域的不同。
const
和let
是相同作用域,区别就是不可被重新赋值。
1. var定义的是全局变量
var a = 10;
console.log(window.a); // 10
let b = 10;
console.log(window.b); // undefined
const c = 10;
console.log(window.c); // undefined
2. function里的作用域
作用域就是可以 访问到这个变量的范围。
如果var
定义在function外面,则作用域是全局的,如果定义在function里面,var
的作用域是function。
而let
和const
定义的变量的作用域都是包裹着它的大括号里的代码块。并且,let
和const
定义的变量不会被hoisting
function funcVar() {
if (true) {
var tmp = 123;
}
console.log(tmp); // 123
}
function funcConst() {
if (true) { // <--这里开始
const tmp = 123;
}// <--这里结束
console.log(tmp); // ReferenceError: tmp is not defined
}
let x = 10;
if (x == 10) {// <--这个x是外面的x
let x = 20; // 里面重新定义了一个x,这个x的作用域只在代码块里
console.log(x); // 20 -- 里面的x
}// <-- 出了这个块,里面的x就没了
console.log(x); // 10 -- 外面的x
let x = 10;
if (x == 10) {// <--外面的x
x = 20; //还是外面的x
console.log(x); // 20;
}// <--这里面并没有定义x,所以改变的是外层的x,
console.log(x); // 20
3. 用let和 const定义的并不会被hoisting
在js中,可以在变量定义之前使用变量,因为变量的定义会被提到作用域最顶上(看上去的定义的位置其实只是赋值)。这个过程叫做hoisting。
而用let和const定义的变量并不会被hoisting。
function testVar() {
console.log(foo); // undefined
var foo = 'testVar';
}
function testLet() {
console.log(foo); // ReferenceError: foo is not defined
let foo = 'function scope';
}
4. let和var在for循环中的区别
下面的代码中,var
的作用域是全局的(for是个代码块并不是个函数),所以整个过程中只有一个i
,所以在三次循环中,绑定的是统一个i
,这样最后i
变成3了之后,arr1
里面三个函数都返回了3.
const arr1 = [];
for (var i=0; i < 3; i++) {
arr1.push(() => i);
}
arr1.map(x => x()); // [3,3,3]
console.log(i); // 3
下面代码中,let
的作用域是for循环这个代码块,所以arr2
中的三个函数绑定的j
是不同的。 而从for循环之外是没有办法直接访问j
的。
const arr2 = [];
for (let j=0; j < 3; j++) {
arr2.push(() => j);
}
arr2.map(x => x()); // [0,1,2]
console.log(j); // ReferenceError: j is not defined
5. const在for循环中
// TypeError: Assignment to constant variable
for (const i=0; i<3; i++) { //i++ 会引发TypeError, 因为i是const
console.log(i);
}
//但是可以这样用:
for (const i of [0, 1, 2]) { // 每次i都重新绑定。
const message = i + '. ' + 'test'; // 每次for循环都是一个新的作用域。
console.log(message);
}