资讯专栏INFORMATION COLUMN

ES6语法之 let 和 const

Xufc / 1412人阅读

摘要:以往,在中声明变量的唯一方式是使用关键字。这种行为会阻止变量被访问,除非它们被声明了。因此,将一个对象声明为常量必须非常小心。之中,顶层对象的属性与全局变量是等价的。从现在开始,建议放弃使用,改为使用和。

以往,在 JavaScript 中声明变量的唯一方式是使用关键字 var。为了理解为何添加了 letconst,我们先看一个示例,了解使用 var 会带来怎样的麻烦。

var 变量提升

下面代码中你认为运行 getClothing(false) 后的输出是什么?

function getClothing(isCold) {
 if (isCold) {
   var freezing = "Grab a jacket!";
 } else {
   var hot = "It"s a shorts kind of day.";
   console.log(freezing);
 }
}

答案是输出undifind, 本质上,在执行任何 JavaScript 代码之前,所有变量都会被“提升”,也就是提升到函数作用域的顶部。因此在运行时,getClothing() 函数实际上看起来如下所示…

function getClothing(isCold) {
  var freezing, hot;
 if (isCold) {
   freezing = "Grab a jacket!";
 } else {
   hot = "It"s a shorts kind of day.";
   console.log(freezing);
 }
}
let 和 const

使用 letconst 声明的变量解决了这种提升问题,因为它们的作用域是到块,而不是函数。之前,当你使用 var 时,变量要么为全局作用域,要么为本地作用域,也就是整个函数作用域。

如果在代码块(用花括号 { } 表示)中使用 letconst 声明变量,那么该变量会陷入暂时性死区(temporal dead zone),直到该变量的声明被处理。这种行为会阻止变量被访问,除非它们被声明了。

下面例子中, 你认为运行 getClothing(false) 后的输出是什么?

function getClothing(isCold) {
  if (isCold) {
    const freezing = "Grab a jacket!";
  } else {
    const hot = "It"s a shorts kind of day.";
    console.log(freezing);
  }
}

答案是 ReferenceError: freezing is not defined.

关于使用 let 和 const 的规则
let 和 const 还有一些其他有趣特性。

使用 let 声明的变量可以重新赋值,但是不能在同一作用域内重新声明。

使用 const 声明的变量必须赋初始值,但是不能在同一作用域内重新声明,也无法重新赋值。

let instructor = "James";
instructor = "Richard";
console.log(instructor); //Richard
const instructor = "James";
instructor = "Richard";
console.log(instructor); //SyntaxError: Identifier "instructor" has already been declared
使用案例

最大的问题是何时应该使用 letconst?一般法则如下:

当你打算为变量重新赋值时,使用 let

当你不打算为变量重新赋值时,使用 const

因为 const 是声明变量最严格的方式,我们建议始终使用 const 声明变量,因为这样代码更容易读懂,你知道标识符在程序的整个生命周期内都不会改变。如果你发现你需要更新变量或更改变量,则回去将其从 const 切换成 let

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

上面代码中,常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。

顶层对象的属性

顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。ES5 之中,顶层对象的属性与全局变量是等价的。

从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1

let b = 1;
window.b // undefined

上面代码中,全局变量avar命令声明,所以它是顶层对象的属性;全局变量blet命令声明,所以它不是顶层对象的属性,返回undefined

var 该怎么办?

还有必要使用 var 吗?没有了。

在某些情况下有必要使用 var,例如如果你想全局定义变量,但是这种做法通常都不合理,应该避免。从现在开始,建议放弃使用 var,改为使用 letconst

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92395.html

相关文章

  • ES6语法对象的扩展

    摘要:方法的第一个参数是目标对象,后面的参数都是源对象。这个对象的任何变化,都会反映到目标对象上面。方法将和合并成一个新对象,如果两者有同名属性,则的属性值会覆盖的属性值。否则,对象的该属性很可能不起作用。 对象字面量简写法 你可能写过这样的代码:使用和所分配的变量名称相同的名称初始化对象。 let type = quartz; let color = rose; let carat = 2...

    SillyMonkey 评论0 收藏0
  • ES6语法解构赋值

    摘要:类似数组的对象都有一个属性,因此还可以对这个属性解构赋值。默认值解构赋值允许指定默认值当结构不成功时使用默认值。用途变量的解构赋值用途很多。有了解构赋值,取出这些值就非常方便。 原始操作 我们先看看下面的两个代码段,它们使用 ES6 之前的技巧提取数据: const point = [10, 25, -34]; const x = point[0]; const y = point[...

    Hancock_Xu 评论0 收藏0
  • 带你入门 JavaScript ES6 (一)

    摘要:是国际组织于年月日发布的第六版,正式名为通常被成为或。二模版字面量提供一种简单实现表达式嵌套的字符串字面量操作,简而言之就是能够以简单的方法实现字符串拼接操作。 本文同步 带你入门 JavaScript ES6 (一),转载请注明出处。 ES6: 是 ECMA国际组织于 2015 年 6 月 17 日发布的 ECMAScript 第六版,正式名为 ECMAScript 2015,通常被...

    lindroid 评论0 收藏0
  • ES6学习手稿基本类型扩展

    摘要:它是一个通用标准,奠定了的基本语法。年月发布了的第一个版本,正式名称就是标准简称。结语的基本扩展还有一些没有在这里详细介绍。 前言 ES6标准以及颁布两年了,但是,好像还没有完全走进我们的日常开发。这篇文章从ES6的基本类型扩展入手,逐步展开对ES6的介绍。 ECMAScript和JavaScript JavaScript是由Netscape创造的,该公司1996年11月将JavaSc...

    tommego 评论0 收藏0
  • 前端面试ES6篇(高产似母猪)

    摘要:这也是前端面试经常询问的问题,经常问你出现了哪些新的特性,平时又使用过那些。 这也是前端面试经常询问的问题,经常问你es6出现了哪些新的特性,平时又使用过那些。在编写此教程的时候,第一句话往往就是面试常常问到的地方,然后后面就是他的详细解释,面试要求的内容我会用*标记出来。写技术文档是真的累啊,虽然是看别人的文档,但是你得看很多,而且还得自己总结啊。所以说要是觉得对你有用还是帮我点个s...

    BlackMass 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<