Javascript 中 var 和 let 、const 的区别及使用方法
zz_sa 人气:01.var、let、const简介
ECMAScript 变量是松散类型的,意思是变量可以用于保存任何类型的数据。每个变量只不过是一个用于保存任意值的命名占位符。有三个关键字可以声明变量:var、let、const。其中 var 在ECMAScript 的所有版本中都可以使用,而 const 和 let 只能在ECMAScript 6 及更高版本中使用。
var 声明
var 关键字在定义变量中定义和使用中不严格。
1.定义单个变量和同时定义多个变量,在定义多个变量时用逗号隔开。两者不赋值操作。
<script> var userName; var age,address,phone; console.log(userName) console.log(age) console.log(address) console.log(phone) </script>
显然这样输出的值为 undefined 类型。
2.定义单个变量和同时定义多个变量,在定义多个变量时用逗号隔开。两者赋值操作。
<script> var userName = 'sa' var age = 18,address = '南昌',phone = '19238824523' console.log(userName) console.log(age) console.log(address) console.log(phone) </script>
3.var重复声明变量和赋值
在 ECMAScript 中 var 关键字声明的变量可以重复声明,但是赋值操作会覆盖前面已经给变量赋的值。值不仅可以改变数据也可以改变相关的数据类型。
<script> var userName = 'sa' console.log(userName) var userName = 77 // 这边也可以省略var console.log(userName) </script>
4.var 声明的作用域问题
var声明的全局变量全局作用域会挂载到 window 对象上,可以使用window. 的形式访问该变量,或者直接使用变量名的方式。在函数体内部的用var声明的变量是局部变量,当省略 va r时,当前变量会定义为全局变量,但是当我要得到这个变量的值时,我们需要先执行一下函数。
<script> // 定义函数,测试两个变量是否在函数体外部可以使用 function test(){ var msg = '这是局部变量' message = '这是全局变量' } test() console.log(window.message) console.log(message) console.log(msg) </script>
输出结果如下:message 可以获得,但是 msg 不行。关键问题在于,使用 var 声明的变量会成为包含它在函数的局部变量。在一个函数内部定义了一个变量,就意味着该变量将在函数退出时被销毁。
5.var 声明提升
“提升”,也就是把所有的变量声明都拉到函数作用域的顶部。此外,反复多次使用 var 声明同一个变量也没有问题。
<script> // 定义函数,测试变量提升 function test(){ console.log(msg) var msg = '变量' console.log(msg) } test() </script>
正常的我们会认为,变量未定义先使用,会报一个 ~~ is not defined 的错误。但是 var 存在变量提升的行为,以上代码等同于:
function test(){ var msg console.log(msg) msg = '变量' console.log(msg) } test()
两者的输出结果都是如下:
let 声明
let和var的作用差不多,但是有着非常重要的区别。最明显的区别就是,let 声明的范围是块作用域,而 var 声明的范围是函数作用域。
代码块由一个左花括号( { )和一个右花括号( } )标识结束。
1.简单示意 let 和 var 的区别
// let 和 var 的作用域区别 if (true) { var username = 'sa' let msg = 'ss' } console.log(username) console.log(msg)
在当前代码中,let 定义的 msg 只作用与 if 的代码块中,在外部无法使用 msg 该变量。
2. let 不可以重复声明变量,var 可以重复声明变量
<script> var userName var userName let msg let msg </script>
这里提示 msg 重复定义:
3.将 let 和 var 混合重复定义一个变量
<script> var userName let userName let msg var msg // 这边将会报一个重复定义的错误 </script>
当然,JavaScript 引擎会记录用于变量声明的标识符及其所在的块作用域,因此嵌套使用相同的标识符不会报错,因为同一个块中没有重复声明。
<script> let age = 20 console.log(age) // 20 if (true) { let age = 18 console.log(age) // 18 } </script>
4.let 声明的变量不会在作用域中被提升
<script> function test() { console.log(age) let age = 20 } test() </script>
let 声明的变量不会在作用域中被提升是和 var 一个很重要的区别。所以 let 声明变量,必须要先声明后使用,否则报错。
在解析代码时,JavaScript 引擎也会注意在块后面的 let 声明,只不过在此之前不能以任何方式来引用未声明的变量。在 let 声明之前的执行瞬间被称为“暂时性死区”,在此阶段引用任何后面才声明的变量都会抛出 ReferenceError。
5.let的全局声明不会成为 window 对象的属性( var 声明的变量则会)
<script> var msg = '我是var声明的变量' let mess = '我是let声明的变量' console.log(window.msg) console.log(window.mess) </script>
6.条件声明
在使用 var 声明变量时,由于声明会被提升,JavaScript 引擎会自动将多余的声明在作用域顶部合并为一个声明。因为 let 的作用域是块,所有不可能检查是否已经使用了 let 声明过同名变量,同时也就不可能在没有声明的情况下使用它。
错误示范如下:
<script> // 当前声明两个变量 var msg = '我是var声明的变量' let mess = '我是let声明的变量' </script> <script> var msg = 'sa' // 这里没问题,var 存在变量提升声明来处理 let mess = 'ss' // 当之前声明了变量mess,这里将报错,let 不存在变量提升 </script>
<script> let mess // 当前只声明了一个 let 变量 </script> <script> if (typeof mess === 'undefined'){ let mess } mess = 'sa' // mess 被限制在 if {} 作用域块中,当前赋值为全局赋值 console.log(mess) // sa try { console.log(age) } catch (error) { let age } age = 20 // age 被限制在 catch {} 作用域块中,当前赋值为全局赋值 console.log(age) // 20 </script>
注:条件声明比较难以理解,这是一种反模式。这会让我们的程序变得更加难理解。
7.for循环中的 let 声明
当我们在用 var 时,for循环定义的迭代变量会渗透到循环体外部。
for (var i = 0; i < 6; i++) { setTimeout(() => { console.log(i) },0) // 这将打印六个 6 }
这种原因的出现情况是因为由于 var 声明的变量不存在块级作用域在退出循环时,迭代变量保存的是导致循环退出的值:6。在之后执行超时逻辑时,所有的 i 都是同一个变量,最终导致输出的值相同。
使用 let 声明 i 时:
for (let i = 0; i < 6; i++) { setTimeout(() => { console.log(i) },0) // 这将打印六个 6 }
当使用let 声明变量时,JavaScript 引擎在后台会为每一个迭代循环声明一个新的迭代变量,每个 setTimeout 引用的都是不同的变量实例,所以输出的值不同也就是我们期望中的值,也是循环执行过程中每一个迭代变量的值。
在我们对dom节点使用for循环绑定事件时,一般也是用 let 声明迭代变量。
const 声明
const 的行为和 let 基本相同,唯一一个重要的区别就是它在声明变量的同时必须初始化变量,且尝试修改 const 声明的变量会导致运行时错误。
1.const 声明的变量不允许修改
<script> const age = 20 age = 30 </script>
2.const 也是不可重复声明
<script> const age = 20 const age = 30 </script>
3.const 声明的作用域也是块
<script> if (true) { const age = 30 } console.log(age) </script>
4.const 中注意的点
const 声明限制只适用于它指向变量的引用。换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的值不违反 const 的限制。引用未发生改变就行。
例如:修改了对象中 name 的值但不会报错。
const student = { name: 'sa', age: 18, address: 'shanghai' } student.name = 'saa' console.log(student.name) // 输出saa
如果你想用const 声明一个不会被修改的 for 循环变量,那也是可以的。也就是说,每次迭代只是创建一个新变量。这对 for-in 和 for-of 循环都是有意义的。
例如:
for (const key in { a: 1, b: 2, c: 3 }){ console.log(key) }
总结
在我们日常使用变量声明时,遵循一下几点:
1.不使用 var
2.const 优先,let 次之
加载全部内容