let命令

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
for循环的计数器,就很合适使用let命令。

var a = [];
for (var i = 0; i < 10; i++) {a[i] = function () {console.log(i);};
}
a[6](); // 10

输出10,因为这里i是全局变量,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10

var a = [];
for (let i = 0; i < 10; i++) {a[i] = function () {console.log(i);};
}
a[6](); // 6

输出6,因为申明的变量只在块级作用域内有效
for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

for (let i = 0; i < 3; i++) {let i = 'abc';console.log(i);
}
// abc
// abc
// abc

上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
同时let申明的变量不存在变量提升

暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

不允许重复申明
let不允许在相同作用域内,重复申明同一个变量

块级作用域
let实际上为 JavaScript 新增了块级作用域。
为什么需要块级作用域?
ES5中只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景
第一种场景,内部变量可能会覆盖外部变量
第二种场景,用于计数的循环变量泄漏为全局变量
块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了。

// IIFE 写法
(function () {var tmp = ...;...
}());// 块级作用域写法
{let tmp = ...;...
}

块级作用域和函数申明
ES5规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
下面提出一个要注意的点:

// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }(function () {if (false) {// 重复声明一次函数ffunction f() { console.log('I am inside!'); }}f();
}());
// Uncaught TypeError: f is not a function

ES6中理论上是应该得到“I am outside",原因上面咱们已经说了,但实际上会报错,显示f不是一个方法

原来,如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。

允许在块级作用域内声明函数。
函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
同时,函数声明还会提升到所在的块级作用域的头部。
注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。

考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

// 块级作用域内部的函数声明语句,建议不要使用
{let a = 'secret';function f() {return a;}
}// 块级作用域内部,优先使用函数表达式
{let a = 'secret';let f = function () {return a;};
}

还有一个需要注意的地方。ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

// 第一种写法,报错
if (true) let x = 1;// 第二种写法,不报错
if (true) {let x = 1;
}

注意:严格模式下,函数只能声明在作用域的顶层

const命令

const声明一个只读的常量。一旦声明,常量的值就不能改变。
const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。对于const而言,只声明不赋值,就会报错

const的作用域与let命令相同:只在声明所在的块级作用域内有效。
const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
const声明的常量,也与let一样不可重复声明。

本质
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
也就是说const一个对象,允许我们对这个对象添加属性,但是不允许我们将它指向一个另一个对象
如果真的想将对象冻结,应该使用Object.freeze方法。

const foo = Object.freeze({});// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;

上面代码中,常量foo指向一个冻结的对象,所以添加新属性不起作用,严格模式时还会报错。

ES6声明变量的六种方法
ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。

顶层对象的属性
顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。ES5 之中,顶层对象的属性与全局变量是等价的。

window.a = 1;
a // 1a = 2;
window.a // 2

上面代码中,顶层对象的属性赋值与全局变量的赋值,是同一件事。

顶层对象的属性与全局变量挂钩,被认为是 JavaScript 语言最大的设计败笔之一。
ES6 为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1let b = 1;
window.b // undefined

上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。

globalThis对象
全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。
函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。
不管是严格模式,还是普通模式,new Function(‘return this’)(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。

ECMAScript6官方文档学习笔记(一)----let和const命令相关推荐

  1. ZooKeeper官方文档学习笔记03-程序员指南03

    我的每一篇这种正经文章,都是我努力克制玩心的成果,我可太难了,和自己做斗争. ZooKeeper官方文档学习笔记04-程序员指南03 绑定 Java绑定 客户端配置参数 C绑定 陷阱: 常见问题及故障 ...

  2. Open3D官方文档学习笔记

    Open3D官方文档学习笔记 第一部分--点云 1 可视化点云 2 体素降采样 3 顶点法线评估 4 访问顶点法线 补充:Numpy在Open3D中的应用 5 裁剪点云 补充1:获取点云坐标 补充2: ...

  3. ZooKeeper官方文档学习笔记01-zookeeper概述

    纠结了很久,我决定用官方文档学习 ZooKeeper概述 学习文档 学习计划 ZooKeeper:分布式应用程序的分布式协调服务 设计目标 数据模型和分层名称空间 节点和短命节点 有条件的更新和监视 ...

  4. vue.js 2.0 官方文档学习笔记 —— 01. vue 介绍

    这是我的vue.js 2.0的学习笔记,采取了将官方文档中的代码集中到一个文件的形式.目的是保存下来,方便自己查阅. !官方文档:https://cn.vuejs.org/v2/guide/ 01. ...

  5. Android 开发之ViewPage官方文档学习笔记

    2019独角兽企业重金招聘Python工程师标准>>> 以下为官网的官方文档,我将从翻译该文档开始学习. ViewPager extends ViewGroup java.lang. ...

  6. xarray官方文档 学习笔记(序章)

    个人需要开了这个坑 不定时更新 希望能和大家共同学习和交流 工作中难免有不足和错误,希望大家多多批评指正 xarray官方文档首页:http://xarray.pydata.org/en/stable ...

  7. OpenCV-Python官方文档学习笔记(上)

    整理自OpenCV-Python官方文档 一. OpenCV-Python Tutorials 1 安装及验证 2 图片读写,展示 3 视频读写,展示 4 绘图功能(绘制几何形状:线.圆.椭圆.矩形. ...

  8. kafka官方文档学习笔记2--QuickStart

    下载kafka https://www.apache.org/dyn/closer.cgi?path=/kafka/1.0.0/kafka_2.11-1.0.0.tgz 解压安装包 > tar ...

  9. kafka官方文档学习笔记3--配置简述

    Kafka使用key-value键值对格式的配置,这些配置即可以在进程启动时,根据指定的properties文件加载,也可以通过编程的方式,在程序中动态指定:根据集群中角色的不同分为6种配置: bro ...

最新文章

  1. 监控Tomcat解决方案(监控应用服务器系列文章分享)
  2. firefox设置代理服务器
  3. 网络编程释疑之:单台服务器上的并发TCP连接数可以有多少
  4. linux内核打开文件数,放开Linux内核对用户进程可打开文件数和TCP连接的限制
  5. 华为路由器hilink怎么用_华为无线充电怎么用?MatePadPro无线充电使用方法
  6. python xml实例_python解析xml文档实例
  7. Linux驱动(1)--关于驱动的概述
  8. 2017-09-20 前端日报
  9. java集群之间共享数据_多个JVM之间,数据共享的问题?
  10. 终端出厂后自动化运维方案
  11. java 多线程 原子_Java多线程:原子量
  12. 【JIRA学习】 研发项目管理工具工时管理-插件Tempo
  13. 野火指南者(STM32F103)移植LVGL
  14. 《不只是美:信息图表设计原理与经典案例》—— 2.7 更加灵活
  15. 2022 美亚杯 团体赛AGC部分+资格赛服务器部分 所有服务器部分解题思路
  16. Euclid算法和拓展欧几里得算法
  17. 电信物联网卡查询平台具备什么功能
  18. 从Spring源码探究IOC初始化流程
  19. 华为数通笔记-AAA
  20. 微课堂v2 2.1.8以后分销设置就保存不了解决办法 微擎

热门文章

  1. SinoBBD承德德鸣3号楼数据中心获CQC最高等级机房认证
  2. php解析mht,php解析mht文件转换成html
  3. Linux学习 -- Docker的常用命令
  4. 18位身份证包含的信息
  5. IDEA下载与安装,保姆级教程
  6. Android 12 Beta正式亮相;5 月 19 日凌晨 1 点 阔别 2 年的 Google I/O 开发者大会内容集锦
  7. 典型相关分析原理(例题+代码)
  8. Android应用程序开发期末大作业(1)
  9. 解析分账系统,看这篇就够了!
  10. Python调用Geopandas包矢量化txt点数据为shp数据