JavaScript系列文章:从let和const谈起
最近接触到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
JavaScript系列文章:从let和const谈起的更多相关文章
- JavaScript系列文章:谈谈let和const
JavaScript系列文章:谈谈let和const 最近接触到ES6的一些相关新特性,想借let和const两个命令谈谈JavaScript在变量方面的改进. 由于let和const有很多相似之 ...
- Learn-JavaScript-with-MDN 系列文章: 01. var & let & const 对比
Learn-JavaScript-with-MDN 系列文章: 01. var & let & const 对比 var & let & const 区别 https: ...
- JavaScript系列文章:变量提升和函数提升
第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升.这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下. 今天主要介绍以下几点: 1. 变量提升 2. 函 ...
- JavaScript系列文章:详解正则表达式之三
在上两篇文章中博主介绍了JavaScript中的正则常用方法和正则修饰符,今天准备聊一聊元字符和高级匹配的相关内容. 首先说说元字符,想必大家也都比较熟悉了,JS中的元字符有以下几种: / \ | . ...
- JavaScript系列文章:详解正则表达式之二
在上一篇文章中我们讲了正则表达式的基本用法,接下来博主想聊聊其中的细节,今天就从正则修饰符开始吧. 正则修饰符又称为正则标记(flags),它会对正则的匹配规则做限定,进而影响匹配的最终结果.在上次的 ...
- JavaScript系列文章:详解正则表达式之一
正则表达式是一个精巧的利器,经常用来在字符串中查找和替换,JavaScript语言参照Perl,也提供了正则表达式相关模块,开发当中非常实用,在一些类库或是框架中,比如jQuery,就存在大量的正则表 ...
- JavaScript系列文章:不能不看的数据类型检测
由于JavaScript是门松散类型语言,定义变量时没有类型标识信息,并且在运行期可以动态更改其类型,所以一个变量的类型在运行期是不可预测的,因此,数据类型检测在开发当中就成为一个必须要了解和掌握的知 ...
- JavaScript系列文章:自动类型转换-续
在上一篇文章中,我们详细讲解了JavaScript中的自动类型转换,由于篇幅限制,没能覆盖到所有的转换规则,这次准备详细讲解一下. 上次我们提到了对象类型参与运算时转换规则: 1). 在逻辑环境中执行 ...
- JavaScript系列文章:自动类型转换
我们都知道,JavaScript是类型松散型语言,在声明一个变量时,我们是无法明确声明其类型的,变量的类型是根据其实际值来决定的,而且在运行期间,我们可以随时改变这个变量的值和类型,另外,变量在运行期 ...
随机推荐
- 读取数据库数据,并将数据整合成3D饼图在jsp中显示
首先我将生成饼图的方法独立写成一个PieChar.java类,详细代码如下:(数据库需要自己建,如有需要的话) import java.io.IOException; import java.sql. ...
- jquery双向列表选择器DIV模拟版
前段时间项目需要用到双向列表选择,想直接用select,结果发现某些样式不支持,只好用div模拟了以下,功能基本实现能用了,需要其他功能自己加上,譬如列表里展示多列数据等. select版链接:htt ...
- linux php编译安装
1.下载php安装包 http://cn2.php.net/get/php-5.5.36.tar.gz/from/this/mirror 默认情况下Nginx和PHP他俩之间是一点感觉没有的.Apac ...
- ASP.NET Button、ImageButton、LinkButton、HyperLink区别
这4个控件都属于WEB服务器控件,有很多相同的属性和事件.其区别如下所示. 在*.aspx页面中插入Button控件如以下代码所示.<asp:Button runat="server& ...
- 2、项目标准的制定 - PMO项目管理办公室
PMO项目管理办公室应该是针对公司级别的项目内容制定项目标准.这个由公司的项目经理们进行集中讨论,然后将项目标准进行文档化,标准化,从而为公司的项目进行指导性的功能,为公司的项目进行服务.下面对项目标 ...
- 将现有MySQL数据库改为大小写不敏感
用过MySQL的应该都会注意到,默认情况下,Linux下安装的MySQL是大小写敏感的,也就是说Table1和table1可以同时存在.而Windows下的MySQL却是大小写不敏感的,所有表名和数据 ...
- Oracle数据库的 增、删、改、查
有时候数据库的查询语句一时想不起来,或不确定是不是语句写的正确,现在整理了一下标准的基本查询语句,便于以后牢记: .数据操作语言 DML:添加(insert into).修改(update set ...
- Oracle学习笔记十 使用PL/SQL
PL/SQL 简介 PL/SQL 是过程语言(Procedural Language)与结构化查询语言(SQL)结合而成的编程语言,是对 SQL 的扩展,它支持多种数据类型,如大对象和集合类型,可使用 ...
- nandflash驱动程序编写
NAND FLASH是一个存储芯片 那么: 这样的操作很合理"读地址A的数据,把数据B写到地址A" 问1. 原理图上NAND FLASH和S3C2440之间只有数据线, 怎么传输地 ...
- OpenWRT镜像爬虫搭建本地源
网上的爬虫不能用,还是先表达谢意,不过我比较懒不喜欢重复写别人写的教程,只贴出修改,怎么用自己看教程吧. 我自己改了一版可以正常爬: #!/usr/bin/env python #coding=utf ...