最近接触到ES6的一些相关新特性,想借let和const两个命令谈谈JavaScript在变量方面的改进。

由于let和const有很多相似之处,我们就先说一说let吧。

1. let添加了块级作用域

我们知道,JavaScript是没有块级作用域的,如果在块内使用var声明一个变量,它在代码块外面仍旧是可见的:

if (true) {
var foo = 3;
}
console.log(foo); // for (var i = 0; i < 9; i++) {
var j = i;
}
console.log(i); //
console.log(j); // 8

可以看到,在上面代码中,我们虽然是在块内声明的变量,但代码块执行完毕后,依然可以访问到相应的变量,说明JavaScript中没有块级作用域的。

而ES6规范给开发者带来了块级作用域,如果把var换成let命令,我们就可以获得一个块级变量:

if (true) {
let foo = 3;
}
console.log(foo); // Uncaught ReferenceError for (let i = 0; i < 9; i++) {
let j = i;
}
console.log(i); // Uncaught ReferenceError
console.log(j); // Uncaught ReferenceError

从上面代码可以看出,块内声明的变量,块外是不可见的,如果试图引用一个块内用let声明的变量,就会引发一个异常。

2. let约束了变量提升

在JavaScript中,变量提升是很常见的,例如下面这段代码:

function hoistVariable() {
console.log('foo:', foo); // foo: undefined
var foo = 3;
} hoistVariable();

在代码正式执行之前,编译器将会对代码进行预编译分析阶段,在这个阶段,当前作用域中的变量和函数,将被提升到作用域的顶部。(注:目前的JavaScript引擎大都对源代码进行了编译处理,并且预编译和提升是抽象出来的概念。)

经过预编译之后的代码逻辑如下所示:

function hoistVariable() {
var foo;
console.log('foo:', foo); // foo: undefined
foo = 3;
} hoistVariable();

ES6中的let命令规范了变量的声明,约束了变量提升,也就是说,我们必须先声明,然后才可以使用,下面者段代码将会报错:

function nonHoistingFunc() {
console.log('foo:', foo); // Uncaught ReferenceError
let foo = 3;
} nonHoistingFunc();

正确的使用方式是,永远将变量声明置于当前作用域顶部:

function nonHoistingFunc() {
let foo = 3;
console.log('foo:', foo); //
} nonHoistingFunc();

需要注意的是,不管是var还是let,预编译过程中,都发生了变量提升,但与var不同的是,ES6对let进行了约束,其规定,在真正的词法变量声明之前,以任何方式访问let变量都是不允许的,所以从开发人员角度来看,let禁止了变量提升这一行为。

关于这一点,大家可以参考ES6规范中“let和const变量的声明”。

3. let有暂时性死区

只要在块内存在let命令,那么这个变量就绑定到了当前块作用域,不再受外部变量的影响,下面代码将会引发一个错误:

var foo = 3;

if (true) {
foo = 5; // Uncaught ReferenceError
let foo;
}

ES6规定如果块内存在let命令,那么这个块就会成为一个封闭的作用域,并要求let变量先声明才能使用,如果在声明之前就开始使用,它并不会引用外部的变量。

如果把这里的let替换成var,由于不会形成块级作用域,变量的声明其实是与第一行重复了,相当于下面这段代码:

var foo;

foo= 3;

if (true) {
foo = 5;
}

4. let禁止重复声明变量

如上面所述,使用var可以重复声明变量,但let不允许在相同作用域内重复声明同一个变量,下面的代码会引发错误:

// SyntaxError
function func() {
let foo = 3;
var foo = 5;
} // SyntaxError
function func() {
let foo = 3;
let foo = 5;
} // SyntaxError
function func(arg) {
let arg;
}

5. let不会成为全局对象的属性

我们在全局范围内使用var声明一个变量时,这个变量会自动成为全局对象的属性(在浏览器和Node.js环境下,这个全局对象分别是window和global),但let是独立存在的变量,不会成为全局对象的属性:

var a = 3;
console.log(window.a); // let b = 5;
console.log(window.b); // undefined

6. 最后:const命令

以上let所介绍的规则均适用于const命令,不同的是,const声明的变量不能重新赋值,也是由于这个规则,const变量声明时必须初始化,不能留到以后赋值,所以下面的代码是不合法的:

const a = 3;

a = 5;   // Uncaught TypeError: Assignment to constant variable

const b; // Uncaught SyntaxError: Missing initializer in const declaration

以上就是let和const的内容,可以看出,let和const大大改进了ES5的变量机制,使得JS更严谨和规范,随着ES6支持程度的提高,我们应该开始习惯let和const的使用了。

参考资料:

http://es6.ruanyifeng.com/#docs/let

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

http://stackoverflow.com/questions/31219420/are-variables-declared-with-let-or-const-not-hoisted-in-es6

JavaScript:谈谈let和const的更多相关文章

  1. JavaScript系列文章:谈谈let和const

    JavaScript系列文章:谈谈let和const   最近接触到ES6的一些相关新特性,想借let和const两个命令谈谈JavaScript在变量方面的改进. 由于let和const有很多相似之 ...

  2. JavaScript ES6 let、const

    在ES6中,增加了2个声明变量的关键字:let 和 const.在这里将详细介绍let与var的区别.Babel对let的处理以及const的简单使用. 1. let 在ES6规范中增加了 let 关 ...

  3. javascript中var let const三种变量声明方式

    javascript中var let const三种变量声明方式 1.var  ①var表示声明了一个变量,并且可以同时初始化该变量. ②使用var语句声明的变量的作用域是当前执行位置的上下文:一个函 ...

  4. 谈谈let与const

    let 命令 let命令用于声明变量,但是与传统var命令的不同之处在于拥有以下特性: 使用let命令声明的变量只在let命令所在的代码块内有效(我将之称为变量绑定): 不存在变量提升: 存在暂时性死 ...

  5. JavaScript中的var,const,let区别与用法(浅谈)

    let 和 const是(ES6) 新增加了两个重要的 JavaScript 关键字. 1.var全局变量 //全局变量在 JavaScript 程序的任何地方都可以访问 //定义的变量可以修改,如果 ...

  6. <JavaScript>谈谈javascript语法里一些难点问题(一)

    1)    引子 前不久我建立的技术群里一位MM问了一个这样的问题,她贴出的代码如下所示: var a = 1; function hehe() { window.alert(a); var a = ...

  7. <javaScript>谈谈JavaScript中的变量、指针和引用

    1.变量我们可能产生这样一个疑问:编程语言中的变量到底是什么意思呢?事实上,当我们定义了一个变量a时,就是在存储器中指定了一组存储单元,并将这组存储单元命名为a.变量a的值实际上描述的是这组存储单元中 ...

  8. JavaScript Let 和 Const

    来源:菜鸟教程:https://www.runoob.com/js/js-let-const.html JavaScript let 和 const ECMAScript 2015(ECMAScrip ...

  9. JavaScript自学笔记(1)---表单验证,let和const,JSON文件

    今天开个JS自学笔记,本身JS的语法很简单,如果学过Java或者C系的都很容易,就不讨论了.主要是讨论实际应用的问题. 1.表单验证: a.html自动验证: HTML 表单验证可以通过浏览器来自动完 ...

随机推荐

  1. How to Repair GRUB2 When Ubuntu Won’t Boot

    Ubuntu and many other Linux distributions use the GRUB2 boot loader. If GRUB2 breaks—for example, if ...

  2. centos 命令和

    一.远程工具 Window系统上 Linux 远程登录客户端有SecureCRT, Putty, SSH Secure Shell.TightVNC... 重点推荐一款 FinallShell,一般人 ...

  3. 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)

    关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ...

  4. nagios系列(三)之nagios被动监控模式之添加系统负载load、swap、磁盘iostat及memory内存监控详解

    环境: nagios server:192.168.8.42 host_name:node4.chinasoft.com nagios client:192.168.8.41 host_name:no ...

  5. CentOS 6.5环境下使用HAProxy+apache实现web服务的动静分离

    HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案.HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持 ...

  6. css系列之box-sizing

    转载自:http://zh.learnlayout.com/box-sizing.html 人们慢慢的意识到传统的盒子模型不直接,所以他们新增了一个叫做 box-sizing 的CSS属性.当你设置一 ...

  7. webpack 3之hash、chunkhash和contenthash三者的区别

    在使用webpack 3中,文件名的hash值可以有三种hash生成方式,那具体使用哪一种呢? 1.hash 如果都使用hash的话,所有文件的hash都是一样的,而且每次修改任何一个文件,所有文件名 ...

  8. 视觉显著性检测(Visual saliency detection)相关概念

    视觉显著性检测(Visual saliency detection)指通过智能算法模拟人的视觉特点,提取图像中的显著区域(即人类感兴趣的区域). 视觉注意机制(Visual Attention Mec ...

  9. wpf 用户自定义事件传参2

    public delegate void MenuButtonClickEventHandler(object sender, EventArgs e); public event MenuButto ...

  10. String对象的常用属性和方法

    属性 描述 length 在大多数情况下返回字符串中的字符数 方法 描述 toUpperCase() 将字符串修改为大写字母 toLowerCase() 将字符串修改为小写字母 charAt() 以索 ...