ES 6 系列 - 变量声明
let 和 const
let 声明
(一)基本用法
let 声明的变量只在块级作用域内有效,出了该块则报错,最常见且适合的地方在 for 循环中:
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
上面的 i 通过 var 方式声明,(循环次数内)全局有效且只有一个,故每次循环结束后, i 的值会被更新,从而导致在完成所有循环后, a 数组中所有的成员中的 i 均指向最后一次更新的值, 即 10,而使用 let 声明:
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
在每次循环时,该次循环体(代码块)中的 i 只对当前代码块有效,简单而言即:每次循环的 i 相当于一个新的变量,故最终结果是 6 。
(二)var 的变量提升
先看一个例子:
console.log(foo); // 输出undefined
var foo = 2;
按照正常的逻辑,执行 console 时,变量 foo 在内存中并不存在,但是此时会输出 undefined(未赋值) 错误,这就是 var 声明的变量提升:脚本运行时,变量已经存在,但是没有值,最终输出 undefined。使用 let 声明可以避免变量提升。
(三)暂时性死区
只要块级作用域内存在 let 指令,它所声明的变量就 “绑定” 在这个区域,不在受外部影响。
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
如上例所示,在 let 命令之前, tmp 变量都不可用, 这块区域都属于 tmp 的 “死区”,语法上称这种现象为 “暂时性死区”。
注意:1.使用 let 命令时,typeof 不在是一个百分百安全操作;
2.一个比较隐蔽的死区:
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错
调用 bar() 报错的原因在于 x = y 时,y 并没有声明,属于 “死区”,故报错。解决办法是将函数中参数位置对调即可。
同理:
// 不报错
var x = x; // 报错
let x = x;
// ReferenceError: x is not defined
总之:暂时性锁区的本质是,只要一进入当前作用域,所要使用的变量就已经存在,但是处于不可获取的状态,只有等到声明语句出现,才可以获取和使用。
(四)块级作用域
es 5 只有全局和函数作用域两种,接下来看两个 es5 的例子:
1.内层变量覆盖外层变量
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
在 fun f() 中,因为存在 var 指令,故可以说在 f() 中就会存在变量提升的现象(而且优先级貌似蛮高的), 所以这就会导致 console undefined 错误,而不是 console 时间;
2.用来计数的循环变量泄露成全局变量:
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
上例可以看出,在循环结束后,作为控制循环的 i 变量并没有消失,这样就很容易泄露,可能会被恶意利用。
而 let 的使用为 es 6 新増了块级作用域。
const 声明
效果跟 java 中的 static final 差不多;
需要注意:
1.const 的变量声明时必须赋值,否则报错;
2.const 的变量一旦声明,其值只读,不可改变;
3.const 的作用域与 let 相同: 只在声明所在的块级作用域内有效;
4.const 的变量不存在变量提升现象,同样存在暂时性死区;
5.const 的变量,不可重复声明;
6.关于引用类型的对象,一个例子:
const a = [];
a.push('Hello'); // 可执行
a.length = 0; // 可执行
a = ['Dave']; // 报错
常量 a 中存储了一个数组对象的地址,然后这个数组对象中的内容是可变的,但是,最后一行很明显是把一个新的数组对象的地址赋值给 a,这就导致了报错。
ES 6 系列 - 变量声明的更多相关文章
- es6 快速入门 系列 —— 变量声明:let和const
其他章节请看: es6 快速入门 系列 变量声明:let和const 试图解决的问题 经典的 var 声明让人迷惑 function demo1(v){ if(v){ var color='red' ...
- es6系列-变量声明
es6系列所有文章都是阅读阮一峰老师的<ES6标准入门>(第2版)所做的读书笔记.方便日后查阅相关基础知识. git地址: https://github.com/rainnaZR/es6- ...
- Nodejs与ES6系列1:变量声明
1.声明变量 在JS当中一个变量的作用域(scope)是程序中定义这个变量的区域.变量分为两类,全局(global)的和局部的.其中全局变量的作用域是全局性的,即在JavaScript代码中,它处处都 ...
- ES6系列之变量声明let const
ES6也出来好久了,最近闲来无事就想着吧es6做一个系统的总结,巩固自己的知识,丰富一下博客. 为什么叫ES6 实际上是ECMA的一个打的标准,这个标准是在2015年6月发布的,正式的名字实际是es2 ...
- 详解变量声明加 var 和不加 var 的区别
在全局作用域中声明变量加 var 关键字和不加 var ,js 引擎都会将这个变量声明为全局变量,在实际运行时,两种声明方式的变量的行为也是几乎一致的.但是在全局作用域下是否声明一个变量的 时候加va ...
- ES 6 系列 - 赋值的新方式:解构赋值
变量的解构赋值 es 6 允许按照一定的模式,从数组和对象中提取值,然后对变量进行赋值,这被称之为解构: 一.数组的解构赋值 最基本写法: let [a, b, c] = [1, 2, 3]; a / ...
- Js 变量声明提升和函数声明提升
Js代码分为两个阶段:编译阶段和执行阶段 Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容 包括变量声明(var a)和函数声明(function a(){ ...
- js 碎片整理(变量声明,函数作用域)
1.变量声明: 在非严格模式下,函数可以对未声明的变量赋值,而这样赋值的结果就是该变量就会变成全局变量. (function(){ var a = 1; })(); console.log(a) ; ...
- TypeScript 素描-变量声明
博文读自 TypeScript 官方文档而来,不具有学习性,仅是本人学习时记录以供日后翻阅 ,有学习TypeScript的朋友还请去看更为详细的官方文档 /* 变量声明在之前的js中一直是使用var关 ...
随机推荐
- Ubuntu16.04之安装Nutch
1.下载Nutch wget http://mirrors.shu.edu.cn/apache/nutch/2.3.1/apache-nutch-2.3.1-src.zip 2.解压 unzip ap ...
- python推导式创建序列
推导式创建序列 推导式是一个或多个迭代器快速创建序列的一种方式.可以将循环和条件判断结合,简化代码.几个推导式注意符号的使用,比如小括号,方括号,大括号等等. 列表推导式 列表推导式生成列表对象,语法 ...
- linux使用.net core 创建简单的MVC
1 创建MVC 2.修改默认绑定的端口方法 ,在Program.cs 的Build之前加入 .UseUrls("http://*:8888")
- Spring Cloud 入门教程(八): 断路器指标数据监控Hystrix Dashboard 和 Turbine
1. Hystrix Dashboard (断路器:hystrix 仪表盘) Hystrix一个很重要的功能是,可以通过HystrixCommand收集相关数据指标. Hystrix Dashboa ...
- jenkins自动部署应用到tomcat中,编译后shell脚本的简单示例
jenkins的安装这里就不做描述了,很简单的 百度搜索一下即可 这里安装的jenkins-2.39-1.1 wget http://pkg.jenkins-ci.org/redhat/jenkin ...
- HAProxy 参数配置
RabbitMQ集群部署完成,通过HAProxy反向代理来提供统一的对RabbitMQ的访问入口. 1.Haproxy提供高可用性.负载均衡,以及基于TCP和HTTP的应用程序代理.(负载均衡策略有很 ...
- 在Linux的Windows子系统上(WSL)使用Docker(Ubuntu)
背景 平时开发大部人都是在提供了高效GUI的window下工作,但是真正部署环境普遍都是在Linux中,所以为了让开发环境和部署环境统一,我们需要在windows模拟LInux环境,以前我们可能通过虚 ...
- .NET Core 2.1中的分层编译(预览)
如果您是.NET性能的粉丝,最近有很多好消息,例如.NET Core 2.1中的性能改进和宣布.NET Core 2.1,但我们还有更多的好消息.分层编译是一项重要的新特性功能,我们可以作为预览供任何 ...
- Cat8 八类网线是什么?与Cat5、Cat6、Cat7网线的区别?
若您身处于网络通信行业,相信您应该了解一些以太网线缆,比如说超五类网线.六类网线和七类网线等等.但是您知道Cat8 八类网线 是什么吗?它与五类网线.六类/超六类网线及七类/超七类网线有着怎么样的区别 ...
- [LeetCode] 56 - Merge Intervals 合并区间
Given a collection of intervals, merge all overlapping intervals. For example,Given [1,3],[2,6],[8,1 ...