ES6学习 第一章 let 和 const 命令
前言:
最近开始看阮一峰老师的《ECMAScript 6 入门》(以下简称原文)学习ECMAScript 6(下文简称ES6)的知识,整理出一些知识点加上我的理解来做成文章笔记。按照章节为单位一个章节一篇笔记。
文章代码与目录结构和原文不同。
这一章原文链接 let 和 const 命令。
let
let 是用来声明一个变量。
不同与var会存在变量提升(下文有介绍),let所声明的变量值只在let命令所在的代码块内有效。
同一个作用域(下文有介绍)不可使用 let 重复声明同一个变量。
注意:
- 声明变量
- 没有变量提升
- 不可重复声明
- 只在
let命令所在代码块有效
let sample = 1;
sample = 2;
let sample = 2; // 将会报错
{
let sample = 1;
console.log(sample); // 正常输出 1
}
console.log(sample); // 将会报错,因为只在let命令所在代码块有效
const
const 是用来声明一个只读常量。
一旦声明,常量的值就不能改变。如果试着改变常量的值会报错。
并且const 在声明的时候就必须对其赋值,只声明不赋值,也会报错。
同一个作用域不可使用 const 重复声明同一个常量。
const 与let一样,都因为作用域原因,只能在所在代码块中有效。
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
注意:
- 声明常量
- 声明后不可以改变
- 声明的时候必须对其赋值
- 不可重复声明
- 在
const命令所在代码块有效
const sample = 1;
sample = 2; // 将会报错,const 声明的变量不可以重新赋值
const sample; // 直接报错,const 声明的时候必须对其赋值
let 与 const
引入let后,已经可以代替var了,在let与const之中能用const就尽量用const。
let 与 const 不同处
let 与 const 的区别就是一个声明变量一个声明常量,变量可以重新赋值,常量不能重新赋值。
let sampleLet = 2;
const sampleConst = 1;
sampleLet = 3; // 正常
sampleConst = 3; // 报错
let 与 const 相同处
- 都只能先声明后使用,不能变量提升。
- 都不可以在同一个作用域中重复声明
- 都只在命令所在代码块有效
{
sampleLet; // 报错
sampleConst; // 报错
let sampleLet = 2;
const sampleConst = 1;
let sampleLet = 3; // 报错
const sampleConst = 3; // 报错
}
sampleLet; // 报错
sampleConst; // 报错
变量提升(Hoisting)
在ES6之前,使用var声明变量时会产生一种叫做变量提升的特性。
无论是在代码的哪个地方声明的,都会提升到当前作用域的最顶部,这种行为叫做变量提升。
为了纠正这种现象,let 命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错
上文
let与const表示变量不能提升,真的是这样吗?
其实在 JavaScript 中,所有表示var, let, const, function, function*, class的声明都会被提升。
let与const声明变量会在环境实例化时被创建,但是在变量的词法绑定之前不允许以任何方式对其进行访问,也就是说,当你在声明前调用变量将会报错但是报错信息不是未定义而是无法在初始化之前访问。这里也就引出了下一个概念,叫做暂时性死区。
// var 声明会变量提升,不会报错,但是值为 undefined
console.log(sampleVar); // undefined
var sampleVar = 1;
// let 声明不会变量提升,但是报错不是 not defined
console.log(sampleLet); // Cannot access 'sampleLet' before initialization
let sampleLet = 1;
// const 声明不会变量提升,但是报错不是 not defined
console.log(sampleConst); // Cannot access 'sampleConst' before initialization
const sampleConst = 1;
// 直接使用没有声明的变量报错为 ” is not defined “
console.log(sample); //sample is not defined
暂时性死区
ES6 规定,如果代码区块中存在 let 和 const 命令声明的变量,这个区块对这些变量从一开始就形成了封闭作用域,凡是在声明之前就使用这些变量,就会报错。直到声明语句完成,这些变量才能被访问(获取或设置),
这在语法上称为“暂时性死区”(英temporal dead zone,简 TDZ),即代码块开始到变量声明语句完成之间的区域。
var sample = 1;
if (true) {
sample = '1'; // 报错
let sample;
}
简单来说,就是let 和 const 命令声明的变量,在进入这个声明代码所在的作用域时,就已经存在,但是不可以获取或使用,直到声明语句完成,才可以访问。
块级作用域
作用域(scope,或译有效范围)就是变量和函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。
let与const 块级作用域
作用域并不是ES6的新东西,但是在ES5只有全局作用域和函数作用域,为了解决块级作用域,ES6可以使用**let**与**const**声明一个块级作用域的变量。
var 声明的变量具有变量提升特性,所以没有块的概念,可以跨块访问,但不能跨函数。
外层作用域无法读取内层作用域的变量。
{ // 块作用域
var sampleVar = 1;
let sampleLet = 2;
const sampleConst = 3;
console.log(sampleVar); // 成功输出 1
console.log(sampleLet); // 成功输出 2
console.log(sampleConst); // 成功输出 3
}
console.log(sampleVar); // 成功输出 1
console.log(sampleLet); // 报错 not defined
console.log(sampleConst); // 报错 not defined
ES6 允许块级作用域的任意嵌套。
同一个作用域不可使用let或const声明同一个变量,内层作用域可以定义外层作用域的同名变量。
{
{
{
let sample = 'Hello World'; // 外层作用域
{ let sample = 'sample'; } // 不报错
{ console.log(sample); } // 正常输出 ‘Hello World’
}
}
}
块级作用域与函数声明
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。
ES6 规定,块级作用域之中,函数声明语句的行为类似于**let**,在块级作用域之外不可引用。
/*
ES5,这两种情况都是不合法的,因为这两个函数声明都是在块作用域中声明。
但应为浏览器为了兼容以前的旧代码,还是支持在块级作用域之中声明函数。所以不会报错
*/
if (true) {
function sampleFn() {}
}
try {
function sampleFn() {}
} catch(e) {
// ...
}
/*
ES6,函数声明语句的行为类似于let,在块级作用域之外不可引用
*/
if (true) {
sampleFn(); // 正常输出,函数声明语句的行为类似于let
function sampleFn() {
console.log('Hello World');
}
}
// 但其实在块级作用域之外也可以引用函数,只不过值为undefined
if (false) {
function sampleFn() { console.log('Hello World'); }
}
console.log(sampleFn); // 正常输出 undefined
sampleFn(); // 报错为sampleFdddn is not defined
为什么块级作用域之外也可以引用函数呢?
如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定(指函数声明语句的行为),有自己的行为方式。
- 允许在块级作用域内声明函数。
- 函数声明类似于
**var**,即会提升到全局作用域或函数作用域的头部。 - 同时,函数声明还会提升到所在的块级作用域的头部。
注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。
我们应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
// 函数声明语句,不要在块作用域中使用,因为会有变量提升
{
function sampleFn() {
console.log("Hello World");
}
}
// 函数表达式,在块作用域中,函数不会有变量提升
{
const sampleFn = function () {
console.log("Hello World");
}
}
顶层对象
顶层对象,在浏览器环境指的是window对象。
ES5 之中,顶层对象的属性与全局变量是等价的。
ES6 为了改变这一点,
一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;
另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
/*
ES5 之中,顶层对象的属性赋值与全局变量的赋值,是同一件事。
*/
window.sample = 1;
console.log(window.sample); // 正常输出 1
sample = 2;
console.log(window.sample);// 正常输出 2
/*
ES6 之中,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
*/
var sampleVar = 1;
console.log(window.sampleVar) // 正常输出 1
let sampleLet = 1;
console.log(window.sampleLet) // 正常输出 undefined
let sampleConst = 1;
console.log(window.sampleConst) // 正常输出 undefined
window提供全局环境(即全局作用域)所有代码都是在这个环境中运行。
函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。
不管是严格模式,还是普通模式,new Function('return this')(),总是会返回全局对象。
function sampleFn(){
console.log(this);
}
sampleFn(); // 正常输出 输出全局对象 window
function sampleFn1(){
"use strict";
console.log(this)
}
sampleFn1(); // 正常输出 undefined
// 开启严格模式
"use strict";
const sample = new Function('return this')();
console.log(sample); // 正常输出 输出全局对象 window
ES6学习 第一章 let 和 const 命令的更多相关文章
- ES6学习笔记(1)----let和const命令
参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ let和const命令 let 总结1.声明变量基本使用方法与var 相同 不同点 a.在代 ...
- ES6 第一章 let和const命令 具体参照http://es6.ruanyifeng.com
1.let类似于var用用来定义变量 1)let没有预解析,不存在变量提升 // var 的情况 console.log(foo); // 输出undefined var foo = 2; // le ...
- oracle学习 第一章 简单的查询语句 ——03
1.1最简单的查询语句 例 1-1 SQL> select * from emp; 例 1-1 结果 这里的 * 号表示全部的列.它与在select 之后列出全部的列名是一样的.查询语句以分号( ...
- web学习第一章
web学习第一章 我是大概9月10日开始走上IT之路的,一开始学习了小段时间的自动化办公软件, 昨天我开始学习客户端网页编程,我了解什么是WEB,一些比较老古董的计算模式和发展历史,印象最让我深刻 ...
- es6学习笔记1 --let以及const
let语句的基本用法: 1.let声明的变量为块级作用域,只在最近的{}里面有效,如果在外部引用就会报错. { let a = 10; var b = "hello" } ale ...
- Java基础知识二次学习-- 第一章 java基础
基础知识有时候感觉时间长似乎有点生疏,正好这几天有时间有机会,就决定重新做一轮二次学习,挑重避轻 回过头来重新整理基础知识,能收获到之前不少遗漏的,所以这一次就称作查漏补缺吧!废话不多说,开始! 第一 ...
- ES6学习笔记(一)——let和const
1.ES6学习之let.const (1).var.let.const 变(常)量声明 ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景. 在ES6中let就诞生了,实际上它 ...
- Intel汇编语言程序设计学习-第一章 基本概念
第一章基本概念 1.1 简单介绍 本书着重讲述MS-Windows平台上IA-32(Intel Architecture 32bit,英特尔32位体系架构)兼容微处理器的汇编语言程序设计,可以使用I ...
- Asp.Net MVC4 + Oracle + EasyUI 学习 第一章
Asp.Net MVC4 + Oracle + EasyUI 第一章 --操作数据和验证 本文链接:http://www.cnblogs.com/likeli/p/4234238.html 文章集合 ...
- ECMAScript 6 第一天 let和const命令
ES6新增声明变量的方法let命令,const命令. (ES5只有两种声明变量的方法:var 命令和 function 命令.) let命令,用来声明变量. 与var声明变量不同于: 1. let声 ...
随机推荐
- 【Tomcat 组成与工作原理】
Tomcat组成与工作原理 Tomcat 是什么 开源的 Java Web 应用服务器,实现了 Java EE(Java Platform Enterprise Edition)的部 分技术规范,比如 ...
- Qt5.9 UI设计(三)——添加UI、类及资源文件
前言 设计一个软件,最简单的方式就是把控件直接往UI上放,然后再把功能实现了.这样可以实现基本的功能,但是界面不能缩放,如果拖动软件改变界面的大小,界面上的控件就会乱成一团,或者是界面的控件压根就不会 ...
- 【转帖】查看mysql库大小,表大小,索引大小
https://www.cnblogs.com/lukcyjane/p/3849354.html 说明: 通过MySQL的 information_schema 数据库,可查询数据库中每个表占用的空间 ...
- [转帖] Linux命令拾遗-文本处理篇
https://www.cnblogs.com/codelogs/p/16060413.html 简介# 这是Linux命令拾遗系列的第二篇,本篇主要介绍Linux中与文本处理相关的命令,如xargs ...
- 龙芯中标麒麟 上面安装libgdiplus的方法
其实方法与之前的blog 基本上完全一样 但是发现有一个问题 安装完libgdiplus之后必须重启一下才能有效果... CentOS 安装libgdi的方法 1. 安装必须的包 1 yum ins ...
- [转载]关于NSA的EternalBlue(永恒之蓝) ms17-010漏洞利用
2017年5月19日 感谢原作者:http://www.cnblogs.com/cnbluerain/ 好久没有用这个日志了,最近WannaCry横行,媒体铺天盖地的报道,我这 ...
- 大数据平台Bug Bash大扫除最佳实践
一.背景 随着越来越多的"新人"在日常工作以及大促备战中担当大任,我们发现仅了解自身系统业务已不能满足日常系统开发运维需求.为此,大数据平台部门组织了一次Bug Bash活动,既能 ...
- 【OpenAI】ChatGPT函数调用(Function Calling)实践
6月13日OpenAI在Chat Completions API中添加了新的函数调用(Function Calling)能力,帮助开发者通过API方式实现类似于ChatGPT插件的数据交互能力. 本文 ...
- 文盘Rust -- 安全连接 TiDB/Mysql
作者:京东科技 贾世闻 最近在折腾rust与数据库集成,为了偷懒,选了Tidb Cloud Serverless Tier 作为数据源.Tidb 无疑是近五年来最优秀的国产开源分布式数据库,Tidb ...
- git撤销推送到远端仓库的提交commit信息
场景描述 有些时候,我们完成功能后,高兴的推送到远端. 推送到远端之后,我们才发现写错分支了. 这个时候,一万匹马在在内心奔腾而过. 然而,难受是没有用的,我们需要撤销推送到远端的代码 git log ...