变量声明一直是JavaScript中一个需要技巧的部分。在大多数基于C的编程语言中,变量(更正式地说是绑定)在声明的时候创建,然而在JavaScript中并不是这样。在JavaScript中,变量在何处创建取决于你用什么方式声明它。ES6提供了新的声明方式,让你可以更容易控制变量的作用域。接下来将说明为什么用var声明变量容易造成困扰以及ES6的块级绑定。

var声明和提升(var Declarations and Hoisting)

在JavaScript中,用var做变量声明相当于在函数顶部声明变量(如果在函数外面声明,那么变量拥有全局作用域),而不管这个变量实际上在何处声明,这称为提升(hoisting)。下面的例子可以说明什么是提升:

function getValue(condition) {if (condition) {var value = "blue";return value;} else {//在这里value是可以被访问,值为undefinedreturn null;}//在这里value是可以被访问,值为undefined
}

如果你不了解JavaScript,你可能认为变量value只有在condition为true的时候才被创建。但实际上变量value无论如何也会被创建。上面这段代码实际上与下面这段代码效果一样:

function getValue(condition) {var value;if (condition) {value = "blue";return value;} else {return null;}
}

可以看到,value的声明被提升到函数顶部,但是仍然在初始的位置完成初始化操作。这意味着变量value在else分支也可以被访问到,但在else中访问value其值为undefined因为在else块中并没有初始化value。变量提升通常给JavaScript新手带来困惑,并且在实际项目带来bug。因为这个原因,ES6提供了块级作用域选项让开发者更好的控制变量的生命周期。

块级声明(Block-Level Declarations)

块级声明的含义是:在变量声明的块作用域外,不能访问此变量。块级声明以下面两种方式声明:

  (1)在函数内声明

  (2)在块内声明(以{}包含)

很多基于C的语言都支持块级声明,ES6提供块级声明也是想让开发者拥有同样的开发灵活性。

let声明(let Declarations)

let的声明语言和var的声明语言是一样的。你可以将代码中的var用let替换,从而将变量的作用范围限制在当前块内。用let声明的变量不会被提升到块的顶部。最好是在块的最开始部分用let声明变量,这样在整个块内就都能访问到变量。来看下面的示例代码:

function getValue(condition) {if (condition) {let value = "blue";return value;} else {//在这里value不能被访问return null;}//在这里value不能被访问
}

上面的getValue函数实际上很像我们在其他基于C的语言中声明的函数。value变量是用let声明的,不会被提升,所以现在只能在if块内访问到value变量。如果condition为false,那么value变量永远也不会被声明或初始化。

禁止重复声明(No Redeclaration)

如果某个变量已经在作用域内声明,那么用let再次声明这个变量,就会报错。请看下面的代码:

var count = 30;let count = 40;  //报错

在上面的代码中,count被声明两次:var和let各声明一次。因为let不能重复定义一个已经存在的变量,所以上面的代码会抛出错误。但是如果let是在自己块内声明一个同名变量,将不会报错:

var count = 30;if (condition) {let count = 40;  //没有报错
}

这里let定义count变量不会报错,是因为它在if块内创建的,而不是在外部的块。在if块内访问count的值为40,而不是外面的30。这与C/C++等语言的作用方式是一样的。

常量声明(const Declarations)

ES6支持用关键字const作常量声明。用const声明的变量在初始化后不能被修改。每个const变量在声明时必须被初始化,看下面的代码:

const maxItems = 30;const name;  //语法错误,name没被初始化

maxItens在声明时被初始化,而name在声明时未被初始化,因而会报错。

常量声明 vs let声明(Constants vs. let Declarations)

const声明和let声明一样,都是块级声明,也就是说在块内用const声明的变量无法在块外被访问。const声明的变量也不会被提升。看下面的代码:

if (condition) {const maxItems = 5;
}
//这里不能访问到maxItems变量

const另外一个与let相似的性质是,在作用域内也不能重复声明变量。不管这个变量是用var还是let声明的。看下面的代码:

var message = "Hello";
let age = 25;//下面两句都会报错
const message = "Goodbye!";
const age = 30;

在这些相似的性质之外,const和let之间还有一个重要的不同之处。对一个已经用const声明的变量赋值会报错,不管是strict还是non-strict模式:

const maxItems = 5;maxItems = 5;  //报错

const声明对象(Object Declarations with const)

const声明的对象可以修改对象的属性,看下面的代码:

const person = {name: "Nicholas"
};person.name = "Greg";  //没问题//报错
person = {name: "Greg"
};

简单的说就是用const声明的变量,本身绑定的值不能变,但是指向的对象却是可以修改的。

《理解 ES6》阅读整理:块绑定(Block Binding)相关推荐

  1. 《深入理解ES6》笔记——块级作用域绑定(1)

    本章涉及3个知识点,var.let.const,现在让我们了解3个关键字的特性和使用方法. var JavaScript中,我们通常说的作用域是函数作用域,使用var声明的变量,无论是在代码的哪个地方 ...

  2. 机器阅读理解MRC论文整理

    机器阅读理解MRC论文整理 最近发现一篇机器阅读理解整理的博客机器阅读理解整理整理于2020年 论文代码查找网站: https://dblp.uni-trier.de/db/conf/acl/acl2 ...

  3. 如何理解文件存取单位 -- 块(block)

    文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次 ...

  4. ES6专题——整理自阮一峰老师的ECMAScript 6入门

    这里我仅仅是记录了那些我认为值得注意的ES6知识点,详细版请挪步https://es6.ruanyifeng.com/#docs/let let和const命令 let声明的变量只在它所在的代码块有效 ...

  5. 理解es6中的暂时性死区

    引入 什么是作用域? 一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域. 全局作用域 JS中没有明确的全局作用域的概念,只有局部作用域以及全局执行环 ...

  6. NLP-阅读理解:“阅读理解”综述(Machine Reading Comprehension, MRC)【完形填空、多项选择、抽取式(答案片段抽取)、生成式(自由作答)】《机器阅读理解数据集》

    <原始论文:Neural Machine Reading Comprehension: Methods and Trends> 一.阅读理解概述 所谓的机器阅读理解(Machine Rea ...

  7. 文献—Emergent simplicity in microbial community assembly--论文全过程详细阅读整理与翻译

    本文对Emergent simplicity in microbial community assembly-- 论文全过程详细阅读整理 原始文献Goldford J E , Lu N , Bajic ...

  8. 一步一个脚印学习WCF系列之WCF基础术语—绑定(Binding)(五)

    阅读目录 一:为什么会出现绑定? 一:为什么会出现绑定? . 服务之间的通信是多种多样的,有很多种通信模式 . 消息通信模式就有比如:同步请求/应答模式,异步的即发即弃消息等一系列,传递消息的传输协议 ...

  9. WCF 绑定(Binding)

    作者:jiankunking 出处:http://blog.csdn.net/jiankunking 绑定包含多个绑定元素 ,它 们描述了所有绑定要求 .可以创建自定义绑定 ,也可以使用下表中的其中一 ...

最新文章

  1. iphone android 开发指南 http://mobile.tutsplus.com
  2. 20211108 能观能控,可稳可测
  3. Spring JdbcTemplate CRUD增删改查操作
  4. AtomicLong和LongAdder的区别
  5. derby数据库的数据_Derby数据库备份
  6. vue抽屉_VUE组件 之 Drawer 抽屉
  7. 关于测试一个接口的面试题
  8. tomcat ---- web.xml
  9. Spring3.0核心组件的源码简单分析
  10. HTML + CSS + JS知识点复习(第一次)
  11. 杰控连接mysql_杰控FameView在数据库连接和查询方面的应用———FameView组态软件在数据库处理方面的...
  12. 真实网络环境下使用易邮搭建网络邮件服务器并测试通过
  13. Python math.erf() 方法
  14. 企业数字化信息化运营管理规划方案
  15. java 的qq 语音文件怎么打开,用手机java的QQ可以和电脑上的QQ进行语音通话吗?
  16. 心情不好的时候,用 Python 画棵樱花树送给自己吧
  17. 安卓手机怎么录屏?精心挑选这几款录屏软件,个个好用
  18. [VOT15](2021CVPR)Alpha-Refine: Boosting Tracking Performance by Precise Bounding Box Estimation
  19. flutter截取字符串_Flutter Dart List.map() 获取下标
  20. 如何使用MATLAB生成一个FIR低通滤波器?

热门文章

  1. 基于Unity3d 引擎的Android游戏优化
  2. OWASP TOP 10
  3. 008PHP文件处理——文件操作r w (用的比较多) a x(用的比较少) 模式 rewind 指针归位:...
  4. ios打包ipa的四种实用方法
  5. VS2015自定义类模板的方法
  6. fedora17下配置tftp服务器
  7. 递归删除父节点及所有子节点(转)
  8. 配置 Spring.NET
  9. 181920.net用 文字存档
  10. 在Windows下安装labelImg