前言:

最近开始看阮一峰老师的《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 重复声明同一个常量。

constlet一样,都因为作用域原因,只能在所在代码块中有效。

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

注意

  • 声明常量
  • 声明后不可以改变
  • 声明的时候必须对其赋值
  • 不可重复声明
  • const命令所在代码块有效
const sample = 1;
sample = 2; // 将会报错,const 声明的变量不可以重新赋值
const sample; // 直接报错,const 声明的时候必须对其赋值

let 与 const

引入let后,已经可以代替var了,在letconst之中能用const就尽量用const

let 与 const 不同处

letconst 的区别就是一个声明变量一个声明常量,变量可以重新赋值,常量不能重新赋值。

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 命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错

上文letconst表示变量不能提升,真的是这样吗?

其实在 JavaScript 中,所有表示var, let, const, function, function*, class的声明都会被提升。

letconst声明变量会在环境实例化时被创建,但是在变量的词法绑定之前不允许以任何方式对其进行访问,也就是说,当你在声明前调用变量将会报错但是报错信息不是未定义而是无法在初始化之前访问。这里也就引出了下一个概念,叫做暂时性死区

// 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 规定,如果代码区块中存在 letconst 命令声明的变量,这个区块对这些变量从一开始就形成了封闭作用域,凡是在声明之前就使用这些变量,就会报错。直到声明语句完成,这些变量才能被访问(获取或设置),

这在语法上称为“暂时性死区”(英temporal dead zone,简 TDZ),即代码块开始到变量声明语句完成之间的区域。

var sample = 1;
if (true) {
sample = '1'; // 报错
let sample;
}

简单来说,就是letconst 命令声明的变量,在进入这个声明代码所在的作用域时,就已经存在,但是不可以获取或使用,直到声明语句完成,才可以访问。

块级作用域

作用域(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 允许块级作用域的任意嵌套。

同一个作用域不可使用letconst声明同一个变量,内层作用域可以定义外层作用域的同名变量。

{
{
{
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 命令的更多相关文章

  1. ES6学习笔记(1)----let和const命令

    参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ let和const命令 let 总结1.声明变量基本使用方法与var 相同  不同点  a.在代 ...

  2. ES6 第一章 let和const命令 具体参照http://es6.ruanyifeng.com

    1.let类似于var用用来定义变量 1)let没有预解析,不存在变量提升 // var 的情况 console.log(foo); // 输出undefined var foo = 2; // le ...

  3. oracle学习 第一章 简单的查询语句 ——03

    1.1最简单的查询语句 例 1-1 SQL> select * from emp; 例 1-1 结果 这里的 * 号表示全部的列.它与在select 之后列出全部的列名是一样的.查询语句以分号( ...

  4. web学习第一章

    web学习第一章   我是大概9月10日开始走上IT之路的,一开始学习了小段时间的自动化办公软件, 昨天我开始学习客户端网页编程,我了解什么是WEB,一些比较老古董的计算模式和发展历史,印象最让我深刻 ...

  5. es6学习笔记1 --let以及const

    let语句的基本用法:  1.let声明的变量为块级作用域,只在最近的{}里面有效,如果在外部引用就会报错. { let a = 10; var b = "hello" } ale ...

  6. Java基础知识二次学习-- 第一章 java基础

    基础知识有时候感觉时间长似乎有点生疏,正好这几天有时间有机会,就决定重新做一轮二次学习,挑重避轻 回过头来重新整理基础知识,能收获到之前不少遗漏的,所以这一次就称作查漏补缺吧!废话不多说,开始! 第一 ...

  7. ES6学习笔记(一)——let和const

    1.ES6学习之let.const (1).var.let.const 变(常)量声明 ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景. 在ES6中let就诞生了,实际上它 ...

  8. Intel汇编语言程序设计学习-第一章 基本概念

    第一章基本概念 1.1  简单介绍 本书着重讲述MS-Windows平台上IA-32(Intel Architecture 32bit,英特尔32位体系架构)兼容微处理器的汇编语言程序设计,可以使用I ...

  9. Asp.Net MVC4 + Oracle + EasyUI 学习 第一章

    Asp.Net MVC4 + Oracle + EasyUI  第一章 --操作数据和验证 本文链接:http://www.cnblogs.com/likeli/p/4234238.html 文章集合 ...

  10. ECMAScript 6 第一天 let和const命令

    ES6新增声明变量的方法let命令,const命令. (ES5只有两种声明变量的方法:var 命令和 function 命令.) let命令,用来声明变量. 与var声明变量不同于: 1.  let声 ...

随机推荐

  1. linux route 命令

    route 管理路由表         要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现.在Linux系统中,设置路由通常是为了解决以下问题:该Linux ...

  2. 【面试题精讲】MySQL中覆盖索引是什么

    有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 在MySQL中,覆盖索引是一种特殊类型的索引,它 ...

  3. [转帖]Oracle 23c 才支持 TLS1.3

    Transport Layer Security 1.3 Protocol Now Supported in Oracle Database Starting with Oracle Database ...

  4. Springboot开发的应用为什么这么占用内存

    Springboot开发的应用为什么这么占用内存 Java的原罪 Java 程序员比 c或者是c++程序员相比轻松了很多. 不要管理繁杂的内存申请与释放,也不用担心因为忘记释放内存导致很严重的内存泄漏 ...

  5. [转帖]JVM——内存区域:运行时数据区域详解

    https://www.jianshu.com/p/cded765cfd1b 关注:CodingTechWork,一起学习进步. 引言   我们经常会被问到一个问题是Java和C++有何区别?我们除了 ...

  6. 使用smem 计算Oracle用户下内存占用情况.

    1. 本来计划使用 ps 命令进行查看, 但是发现ps 最多查询出来的是 RSS的内存数据, 会多添加很多冗余的内存数据量进来, 于是作罢 2. 找了下公司的方神, 说可以使用smem 然后简单看了下 ...

  7. UOS可能的来源

    1050a 行业版 是基于 阿里的Anolis 1050d 企业版 是基于debian 1050e 欧拉版 是基于华为欧拉 euler

  8. Oracle DBCA 静默删除以及建库的脚本

    No.1 背景 公司最近有一个测试环境需要重新备份恢复 但是里面有6个数据库实例 400多G的数据文件. 一般情况下 需要drop user xxx cascade ; 然后执行 drop table ...

  9. 【JS 逆向百例】网洛者反爬练习平台第六题:JS 加密,环境模拟检测

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...

  10. TienChin-课程管理-创建工程

    创建方式与之前一样,如下奉上 generateCourse 代码. @Test void generateCourse() { String path = "E:\\Desktop\\Tie ...