一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
let、const、与var的区别?
- var定义的变量可被更改,如果不初始化而直接使用也不会报错
- let定义的变量和var类似,但作用域在当前声明的范围内
- cons定义的变量只可初始化一次且作用域内不可被更改,使用之前必须初始化
-
var
-
var 声明作用域
使用var操作符定义的变量会成为包含它的函数的局部变量
例如:使用var在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁
function test(){ var msg = "hello"; //局部变量 } test(); console.log(msg); //报错(msg is not defined) //这里msg是在test函数内部定义的,调用test()函数之后,变量msg会随即被销毁,因此控制台会报错不过,需要注意的是,如果函数内定义变量时省略var,此时创建的就是一个全局变量;只要调用一次test函数,就会定义msg变量,并且可以在函数外部访问到。(虽然可以通过省略var定义全局变量,但不推荐这样做)
-
var 声明提升
使用var 声明的变量会自动提升到函数作用域顶部;
function foo() { console.log(num); var num = 13; } foo(); //undefined运行后发现并没报错,是因为运行时把它看成等价于如下代码:
function foo() { var num; console.log(num); num = 13; } foo(); //undefined这就是所谓的提升(host),也就是把所有变量声明都拉到函数作用域的顶部。还有,反复多次使用var声明同一个变量也没有问题。
-
-
let
-
let与var的作用差不多,但有着非常重要的区别。最明显的就是,let声明的范围是块作用域,而var声明的范围是函数作用域。
if(true) { var name = 'Du'; console.log(name); //Du } console.log(name); // Duif(true) { let age = 18; console.log(age); // 18 } console.log(age); // ReferenceError:age未定义在这里,age之所以不能在if块之外被引用,是因为它的作用域仅限于该块内部。
-
let声明的变量不会在作用域中被提升
-
使用let在全局作用域中声明的变量不会成为window对象的属性(var声明的变量则会)
-
使用var的时候,最常见的问题就是对迭代变量的奇特声明和修改:
for(var i=0; i<5; i++) { setTimeout(() => console.log(i),0) } //你可能以为会输出 0、1、2、3、4 //实际上输出 5、5、5、5、5之所以会出现这样的情况,是因为在退出循环时,迭代变量保存的就是导致退出循环的值( 5 )。在之后执行超时逻辑时,所有的i都是同一个变量,因此输出的都是同一个最终值。而使用let声明时:
for(let i=0; i<5; i++) { setTimeout(() => console.log(i),0) } //输出 0、1、2、3、4JS引擎在后台会为每个迭代循环声明一个新的迭代变量。每个setTimeout引用的都是不同的变量实例,所以会输出我们期望的值。
这种每次迭代声明一个独立变量实例的行为适用于所有风格的for循环,包括for-in和for-of循环
-
-
const
-
const 的行为与let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改const声明的变量的值会导致运行时错误。
-
const声明的作用域也是块
const name = 'joy'; if(true) { const name = 'du'; } console.log(name); //joy
-
声明风格及最佳实践:
- 不使用var
- const 优先,let 次之(使用const声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现非法的赋值操作。在提前知道未来会有修改时,再使用 let)