我是靠谱客的博主 耍酷紫菜,最近开发中收集的这篇文章主要介绍【ES6】变量声明-var-let-const-区别与联系-总结1. var2. let(注意与var的区别)3. const4. 定义变量时,操作符的使用建议5. 总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 1. var
    • 1.1 var 声明作用域
    • 1.2 var 声明提升
  • 2. let(注意与var的区别)
    • 2.1 let 声明作用域(块级作用域)
    • 2.2 暂时性死区
      • 仔细解释一下暂时性死区
    • 2.3 全局声明
    • 2.4 条件声明
    • 2.4 for 循环中的let声明
  • 3. const
  • 4. 定义变量时,操作符的使用建议
  • 5. 总结

  • ECMAScript变量是松散类型的,意思是变量可以用于保存任何类型的数据
  • 每个变量只不过是一个用于保存任意值的命名占位符
  • 有3个关键字可以声明变量:var、const和let
  • 其中,var在ES的所有版本中都可以使用,而const和let只能在ES6及更晚的版本中使用

1. var

var message;

定义了一个名为message 的变量,可以用它保存任何类型的值,不初始化的情况下,变量会保存一个特殊值undefined

1.1 var 声明作用域

  • 使用var 操作符定义的变量会成为包含它的函数的局部变量

1.2 var 声明提升

  • 使用var关键字声明的变量会自动提升(hoist)到函数作用域顶部
function foo() {
console.log(age);
var age = 26;
}
foo(); // undefined

等价于

function foo() {
var age;
console.log(age);
age = 26;
}
foo(); // undefined
  • 这就是所谓的“提升”(hoist),也就是把所有变量声明都拉到函数作用域的顶部。
  • 反复多次使用var声明同一个变量也没有问题

2. let(注意与var的区别)

2.1 let 声明作用域(块级作用域)

  • 与var最明显的区别是,let 声明的范围是块作用域,而var声明的范围是函数作用域
  • let 不允许同一个块作用域中出现冗余声明
 if (true) {
let a = 10;
}
console.log(a) // a is not defined
  • 块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了。
// IIFE 写法
(function () {
var tmp = ...;
...
}());
// 块级作用域写法
{
let tmp = ...;
...
}

2.2 暂时性死区

  • let与var的另一个重要的区别,就是let声明的变量不会在作用域中被提升
  • 在解析代码时,JavaScript 引擎也会注意出现在块后面的let 声明,只不过在此之前不能以任何方式来引用未声明的变量
  • 在let声明之前的执行瞬间被称为“暂时性死区”(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出 ReferenceError
  • 总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。
var num = 10;
if(true){
console.log(num); // Uncaught ReferenceError: Cannot access 'num' before initialization
let num = 20;
}

仔细解释一下暂时性死区

  • 只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
  • ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。
  • 凡是在声明之前就使用这些变量,就会报错。
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
  • “暂时性死区”也意味着typeof不再是一个百分之百安全的操作。(在没有let之前,typeof运算符是百分之百安全的,永远不会报错)
typeof x; // ReferenceError
let x;
typeof undeclared_variable // "undefined"
// 不报错
var x = x;
// 报错
let x = x;
// ReferenceError: x is not defined
  • 总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量

2.3 全局声明

  • 与var 关键字不同,使用let 在全局作用域中声明的变量不会成为window 对象的属性(var 声明的变量则会)
  • 不过,let声明仍然是在全局作用域中发生的,相应变量会在页面的生命周期内存续

2.4 条件声明

  • 因为let的作用域是块,所以不可能检查前面是否已经使用let声明过同名变量,同时也就不可能在没有声明的情况下声明它
<script>
var name = 'Nicholas';
let age = 26;
</script>
<script>
// 假设脚本不确定页面中是否已经声明了同名变量
// 那它可以假设还没有声明过
var name = 'Matt';
// 这里没问题,因为可以被作为一个提升声明来处理
let age = 36;
// 如果age之前声明过,这里会报错
</script>
<script>
let name = 'Nicholas';
let age = 36;
</script>
<script>
if (typeof name === 'undefined') {
let name;
// name 被限制在if {} 块的作用域内
}
// 因此这个赋值形同全局赋值
name = 'Matt';
try {
console.log(age); // 如果age 没有声明过,则会报错
}
catch(error) {
let age;
// age 被限制在catch {}块的作用域内
}
// 因此这个赋值形同全局赋值
age = 26;
</script>
  • 不能使用let进行条件式声明

2.4 for 循环中的let声明

for (var i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // 5
for (let i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // ReferenceError: i 没有定义
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 你可能以为会输出0、1、2、3、4
// 实际上会输出5、5、5、5、5
for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 会输出0、1、2、3、4
  • 另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
  • 上面代码正确运行,输出了 3 次abc。
  • 这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。

3. const

  • const 的行为与let基本相同(1. 块级作用域),唯一一个重要的区别是用它声明变量时必须同时初始化变量(2. 初始化必须赋值),且尝试修改const声明的变量会导致运行时错误(3. 不可修改)。
  • const 声明的限制只适用于它指向的变量的引用。如果const变量引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制。

4. 定义变量时,操作符的使用建议

  1. 不使用var

  2. const优先,let次之
    这样可以让开发者更有信心地推断某些变量的值永远不会变,同时也能迅速发现因意外赋值导致的非预期行为

5. 总结

varletconst
函数作用域块级作用域块级作用域
变量提升不存在变量提升不存在变量提升
值可更改值可更改值不可更改
全局声明会变成window对象的属性不会不会
可以重复声明不可以重复声明不可以重复声明
可以条件式声明不可以条件式声明不可以条件式声明
迭代变量保存的是退出循环的值每次迭代声明一个独立实例报错,因为值不可改变

最后

以上就是耍酷紫菜为你收集整理的【ES6】变量声明-var-let-const-区别与联系-总结1. var2. let(注意与var的区别)3. const4. 定义变量时,操作符的使用建议5. 总结的全部内容,希望文章能够帮你解决【ES6】变量声明-var-let-const-区别与联系-总结1. var2. let(注意与var的区别)3. const4. 定义变量时,操作符的使用建议5. 总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部