JavaScript中的var,let和const之间的区别

Posted by cl9000 on March 18, 2020

人只有献身于社会,才能找出那短暂而有风险的生命的意义。 ——<爱因斯坦>

作者:Ashish Lahoti

译者:cl9000

原文:https://codingnconcepts.com/javascript/difference-between-var-let-and-const/

ES2015 (ES6)中新增的一个不错的特性是为变量声明引入了 letconst 关键字。可以互换地使用 var、let和const关键字来声明变量,尽管这在它们的作用域、用法和提升方面有所不同。如果
你还没有意识到这些差异,请继续阅读…

Scope 作用域

作用域基本上是指变量的可访问性。变量可以有三种作用域:-

1. 全局作用域 Global Scope

当变量定义在函数外部并且在任何地方都可以访问时。所有的var, let和const都是全局作用域。

2. 函数作用域 Function Scope

使用 var 定义的变量是函数作用域的,因为如果它是在函数内部定义的,那么它们的可见性仅限于函数或嵌套函数。当你尝试在函数外使用它时,你会得到一个错误。

1
2
3
4
5
6
function myFn() {
var foo = 'peekaboo!';
console.log(foo); // Prints 'peekaboo!'
}

console.log(foo); // ReferenceError: foo is not defined

3. 块作用域 Block Scope

使用 let或const 定义的变量是块范围的,因为如果它定义在代码块内(在花括号{}之间的代码),它们的可见性仅限于代码块,任何嵌套的块。当你尝试在块之外使用它时,你会得到一个错误。

1
2
3
4
5
6
7
8
9
10
11
if (true) {
var foo = 'peekaboo!';
let bar = 'i see u';
const baz = 'baby blue!';
console.log(foo); // Prints 'peekaboo!';
console.log(bar); // Prints 'i see u';
console.log(baz); // Prints 'baby blue!';
}
console.log(foo); // Prints 'peekaboo!';
console.log(bar); // ReferenceError: bar is not defined
console.log(baz); // ReferenceError: baz is not defined

使用

1. var

ES6 之前,var 是变量声明的唯一关键字。

for 循环之外执行 var 操作

1
2
3
4
for (var i = 0; i < 3; i++) {
console.log(i); // Prints 0, 1 and 2
}
console.log(i); // Prints 3

因为 var 是函数作用域的。变量i可以在for循环之外被访问(代码块).

var 重新分配

使用var的变量可以重新赋值,也可以重新定义。

1
2
3
4
5
6
7
function myFn() {
var foo = 1;
foo = 30;
var foo = 101;
console.log(foo); // Prints 101
}
myFn();

2. let

for 循环之外执行 let 操作

1
2
3
4
for (let i = 0; i < 3; i++) {
console.log(i); // Prints 0, 1 and 2
}
console.log(i); // ReferenceError: i is not defined

因为 let 是块范围的。变量 ifor 循环之外是不可访问的(代码块).

let 重新分配和重新定义
使用let的变量可以重新赋值,但不能重新定义。

1
2
3
4
5
6
7
function myFn() {
let foo = 1;
foo = 30;
let foo = 101;
console.log(foo);
}
myFn();

Output

Uncaught SyntaxError: Identifier ‘foo’ has already been declared

但是,如果 let 变量在不同的作用域中定义,就不会出现错误。

1
2
3
4
5
6
7
8
9
10
11
12
let foo = 1;
function myFn() {
let foo = 2;
console.log(foo);

if(true){
let foo = 3;
console.log(foo);
}
}
console.log(foo);
myFn();

Output

1
2
3

为什么没有错误? 这是因为这三个实例都被视为不同的变量,因为它们具有不同的作用域。

3. const

关键字 const 类似于 let ,它是块作用域的,但是你不能给它重新赋值。

1
2
const PI = 3.1415;
PI = 5; // "TypeError: Assignment to constant variable.

但是,仍然可以将新项推入数组常量或添加到对象中。下面的两个代码段可以毫无怨言地工作,因为我们并没有试图重新分配变量:

1
2
const someArr = [3, 4, 5];
someArr.push(6);
1
2
3
4
5
6
const someObj = {
dog: 'Skip',
cat: 'Caramel',
bird: 'Jack'
};
someObj.camel = 'Bob';

提升 Hoisting

提升是一种 ·JavaScript` 机制,在代码执行之前将变量和函数声明移动到其作用域的顶部

对于 var 变量,它们的值在提升过程中被初始化为 undefined

1
2
3
4
5
6
7
8
9
console.log(foo); 
var foo = 1;
console.log(foo);

console.log(bar);
bar = 2;
console.log(bar);

var bar;

被解释为:

1
2
3
4
5
6
7
8
9
10
var foo;
var bar;

console.log(foo); // undefined
foo = 1;
console.log(foo); // 1

console.log(bar); // undefined
bar = 2;
console.log(bar); // 2

你能猜到下面代码片段的输出是什么吗?

1
2
3
4
5
6
7
8
9
var foo = 1;

function myFun(){
console.log(foo);

var foo = 2;
}

myFun();

你猜 foo = 1 还是 foo = 2 ?

都不是。它将打印未定义。让我们看看在提升过程中编译器是如何解释它的

1
2
3
4
5
6
7
8
9
10
11
12
var foo;
foo = 1;

function myFun(){

var foo; // var hoisted and initialized with undefined
console.log(foo); // undefined

foo = 2;
}

myFun();

就像 var 一样,let 声明也被挂起在顶部,但不像 var 被初始化为 undefined , let 变量没有初始化。因此,如果你尝试在声明之前使用 let 变量,你会得到一个引用错误。const 变量在提升方面与let 变量相似。

1
2
console.log(foo);
let foo = 1;

Output

ReferenceError: foo is not defined

你能猜到下面代码片段的输出是什么吗?

1
2
3
4
5
6
7
8
9
let foo = 1;

function myFun(){
console.log(foo);

let foo = 2;
}

myFun();

你猜 foo = undefined 吗?

不 它不是。让我们看看在提升过程中编译器是如何解释它的

1
2
3
4
5
6
7
8
9
10
11
12
13
let foo;
foo = 1;

function myFun(){

let foo; // let hoisted without initialization unlike var
console.log(foo); // ReferenceError: Cannot access 'foo' before initialization

foo = 2;

}

myFun();

总结 Summary

作用域 值更新 重新定义变量 提升
var 函数作用域 yes yes(在作用域内) 初始化为undefined
let 块作用域 yes no(在块作用域内)但yes(块作用域外) 变量未初始化
const 块作用域 no no 未初始化的变量
  • var 变量是函数作用域,而 let和const 是块作用域。
  • var变量可以在其作用域内更新和重新声明; let变量可以更新,但不能重新声明; const变量既不能更新也不能重新声明。
  • 它们都被悬挂在作用域的顶部,但是当 var 变量用undefined初始化时,let和const变量则不初始化。
  • var和let可以在声明时不进行初始化,而const则必须在声明时进行初始化。

参考

原文 - https://codingnconcepts.com/javascript/difference-between-var-let-and-const/



支付宝打赏 微信打赏

赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!