鉴于最近用 vuejs 框架开发项目,其中有很多涉及到 es6 语法不太理解所以便认真地读了一下这本书。

  地址:http://es6.ruanyifeng.com/#README

  第一章:let ,const 命令以及块级作用域

  es6 新增了 let 和 const 这两个变量的声明关键字,这样大大的强化了 js 变量的合理程度以及修补了很多es6 版本前出现的bug。他们有着以下的特性:

   一:let 的声明

  1.1 用let 声明的变量会将变量绑定到声明时所属的语句块中,并且语句块外部不可访问

  例如下面这个例子:

for (let i = 0; i < 10; i++) {
// ...
} console.log(i);
// ReferenceError: i is not defined

在es6 版本以前,循环条件内的变量如果用var 声明则循环结束后还可以在外部环境中访问,而是用let 声明不会。在每一次循环中let 都会被重新声明一次并且在本轮循环中有效

在for 循环中还有一个特别的地方,条件块和执行块都是一个独立的块作用域因此下面的例子也能正常运行

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

即使是声明了同名变量但因为是在不同的块作用域中声明,所以不会报错,但我觉得为了阅读代码有更好的体验还是尽量别用同名变量

1.2 用let 声明的变量不存在变量提升

变量提升一直是js 的一个通病,好听一点是叫做“特征”,这不仅颠覆了编程语言执行顺序还会带来一些不可思议的问题,如下:

// var 的情况
console.log(foo); // 输出undefined
var foo = 2; // let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

第一种用var 声明的变量在代码执行前就已经存在变量的提升可以拆解为如下步骤:

// var 的情况
var foo;
console.log(foo); // 输出undefined
foo = 2;

所以才会输出 undefined

而let 的出现改变了这个“特征”,使js 不存在变量声明,假若在声明变量语句前调用变量则会报错

1.3 暂时性死区

在一个语句块中用let 声明一个变量,这个变量便会绑定在这个语句块中不受外部变量影响,例子:

var tmp = 123;

if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}

上面例子中因为tmp 是在if 语句块中声明所以tmp 便绑定在了if 语句块中,语句块中又会重新判断一次块内语句声明的合理性,而tmp 的调用时在声明前所以报错

总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。

1.4 不允许重复声明

用let 声明的变量不能同名,否则报错,另外在函数内部用let 声明的变量也不可以与参数同名

二:块级作用域

2.1 没有作用域的日子

es5 没有块级作用域的概念,这样导致了内层变量覆盖外层变量 以及 用来计数的循环变量泄露为全局变量   

内层变量覆盖外层变量的例子:

var tmp = new Date();

function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
} f(); // undefined

上面说过var 声明的变量会被提升,所以上面的例子可以拆解成这样:

var tmp = new Date();

function f() {
var tmp;
console.log(tmp);
if (false) {
tmp = 'hello world';
}
} f(); // undefined

因为变量提升 tmp 未被赋值就被调用(函数的后期也没有为tmp 赋值),所以导致函数输出为undefined

用来计数的循环变量泄露为全局变量例子:

var s = 'hello';

for (var i = 0; i < s.length; i++) {
console.log(s[i]);
} console.log(i); //

上面也说过,用let 在循环条件内部声明变量的好处就是不会将变量泄露到全局作用域,而用var 则会。es5的解决办法是用闭包模拟块作用域迫使循环条件内部的变量不泄露

2.2 es6 作用域的来袭

先看个例子:

function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); //
}

函数体内部定义了一个块作用域,其上级作用域就是函数体,当在if 语句作用域外调用 变量n 的时候是不会调用到if 语句内部的变量的只会调用会输出语句所属语句块中的对应变量。

假如用var 声明便会这样:

function f1() {
var n = 5;
if (true) {
var n = 10;
}
console.log(n);
} f1(); // 输出10

因为变量的提升影响了输出结果,分解:

function f1() {
var n;
n = 5; if (true) {
n = 10;
} // 判断条件成立 变量n 被重新赋值为10
console.log(n);
} f1(); // 故输出10

2.3 块作用域可嵌套,在不同的块作用域声明同名变量不会报错

{{{{
let insane = 'Hello World';
{let insane = 'Hello World'}
}}}}; // 没问题

块作用域的出现使原来的 iife(自执行函数)可以停止使用了

2.4 块级内部声明函数可能会因为浏览器的差异导致不可思议的效果

es5 规则中函数只能在全局作用域中声明,不能再局部作用域声明,但是浏览器并没有遵循这个原则为了兼容以前的旧代码这种声明是正常的

而es6 有了块作用域的概念,明确指明可以在块级作用域中声明函数,例子:

function f() { console.log('I am outside!'); }

(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
} f();
}());

在es5 中运行会输出  I am inside! 因为函数声明的提升,而在es6 中调用理论会输出  I am outside!,而实际上浏览器执行会直接报错那是因为为了减轻老代码不兼容的问题浏览器可以不按规则办事,具体如下:

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。

所以在支持es6 的浏览器执行上面例子语句其实会执行如下语句

// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
var f;
if (false) {
f = function() { console.log('I am inside!'); }
} f();
}());
// Uncaught TypeError: f is not a function

考虑到浏览器的差异,所以尽量少在块作用域中使用函数声明而改成用函数表达式。

另外ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

// 不报错
'use strict';
if (true) {
function f() {}
} // 报错
'use strict';
if (true)
function f() {}

2.5 do 表达式

块作用域没有返回值,如果在块作用域前面加上一个 do 关键字可以使块作用域有返回值,在chrome 上没有实验出来只能贴下阮一峰老师的实例代码了

let x = do {
let t = f();
t * t + 1;
};

x 会得到块作用域的返回值(尽管不知道哪里才是返回的值)

三:const(constant ) 声明

3.1 const 声明的变量是一个常量,声明之后常量的值不可改变而且一旦声明就必须要初始化

声明常量后再次赋值的错误:

const PI = 3.1415;
console.log(PI); // 3.1415 PI = 3;
// 报错 TypeError: Assignment to constant variable.

声明常量但不赋初始值的错误:

const foo;
// SyntaxError: Missing initializer in const declaration

3.2 const 声明的常量和 let 声明的变量一样:

  1、都会绑定在声明的语句块中,在语句块外调用会报错

  2、不存在变量提升,存在暂时性死区,只能在声明的位置后面使用

  3、不能重复声明

3.3 const 声明的常量是一个基础类型,那么它保证这个基础类型的值不变;如果const 声明的常量是一个引用类型,那么它保证这个引用的指针不变

对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。

对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。例如我们改变对象中某个键的对应值,在常量声明下是可以继续运行的不会报错。

如果想完全冻结对象可以用使用 Object.freeze()

读阮一峰老师 es6 入门笔记 —— 第一章的更多相关文章

  1. 【js 笔记】读阮一峰老师 es6 入门笔记 —— 第一章

      鉴于最近用 vuejs 框架开发项目,其中有很多涉及到 es6 语法不太理解所以便认真地读了一下这本书. 地址:http://es6.ruanyifeng.com/#README 第一章:let ...

  2. 【js 笔记】读阮一峰老师 es6 入门笔记 —— 第二章

    第二章:变量的解构赋值 在es6 版本前,如果要为多个变量赋不同值,我想是件比较麻烦的事情.但es6 版本新推出了一个新技术那就是今天的主角变量的解构赋值. 变量解构赋值分为两种方法:数组解构赋值 和 ...

  3. 关于阮一峰老师es6(第三版)中管道机制代码的理解浅析

    最近正在学习阮一峰老师的es6(第三版)教材,在学到第七章<函数的扩展>中的箭头函数嵌套时,文中提到了一个关于“管道机制”的示例,文中源代码如下: //es6(第三版)教材中的管道机制源代 ...

  4. 读阮一峰《ECMAScript 6 入门》小结

    读阮一峰<ECMAScript 6 入门>小结,http://es6.ruanyifeng.com/ 1. ES6简介 Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转 ...

  5. react 入门教程 阮一峰老师真的是榜样

    -  转自阮一峰老师博客 React 入门实例教程   作者: 阮一峰 日期: 2015年3月31日 现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Nati ...

  6. ES6特性:(阮一峰老师)学习总结

    ES6(阮一峰)学习总结   1.块级作用域的引入 在ES6之前,js只有全局作用域和函数作用域,ES6中let关键字为其引入了块级作用域. { var a = 5; let b = 6; } con ...

  7. ES6入门笔记

    ES6入门笔记 02 Let&Const.md 增加了块级作用域. 常量 避免了变量提升 03 变量的解构赋值.md var [a, b, c] = [1, 2, 3]; var [[a,d] ...

  8. 《JavaScript高级程序设计》笔记——第一章到第三章

    2019年,新年伊始,我打算好好重读一下<JavaScript高级程序设计>这本前端必备经典书.每天半小时. 以下内容摘自<JavaScript高级程序设计> 2019-2-1 ...

  9. 《进击吧!Blazor!》系列入门教程 第一章 8.部署

    <进击吧!Blazor!>是本人与张善友老师合作的Blazor零基础入门教程视频,此教程能让一个从未接触过Blazor的程序员掌握开发Blazor应用的能力. 视频地址:https://s ...

随机推荐

  1. 201521123003《Java程序设计》第2周学习总结

    1. 本章学习总结 你对于本章知识的学习总结 学习了java中各种数据类型的使用 掌握了基本类型的转换 了解string和stringbuilder的区别以及字符串池的原理 学会了使用package管 ...

  2. 201521123059 《Java程序设计》第十三周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 1.协议 --网络中为了进行数据交换(通信)而建立的规则.标准或约定(=语义+语法+规则),比如http, ...

  3. 201521123015 《Java程序设计》第13周学习总结

    1. 本周学习总结 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? IP地址不同 ...

  4. JAVA课程设计个人博客 学生成绩管理 201521123014 黄绍桦

    1. 团队课程设计博客链接 http://www.cnblogs.com/kawajiang/p/7062407.html 2.个人负责模块或任务说明 本人主要负责DAO模式.添加和修改学生的信息功能 ...

  5. java web:在eclipse中如何创建java web 项目

    Eclipse创建java web工程 eclipse版本:eclipse-jee-4.5-win32-x64 tomcat版本:apache-tomcat-7.0.63-windows-x64 jd ...

  6. SparkStreming之updateStateByKey

    正文 上一篇简单的写了一个socketTextStream的demo,这个问题就是每一次不能将之前和之后的数据进行合并统一.接下来我们通过demo进行把着这个问题解决. val conf = new ...

  7. 微信小程序语音识别服务搭建全过程解析(项目开源在github)

    silk v3录音转olami语音识别和语义处理的api服务(ubuntu16.04服务器上实现) ## 重要的写在前面 重要事项一: 目前本文中提到的API已支持微信小程序录音文件格式:silk v ...

  8. BZOJ1059_矩阵游戏_KEY

    1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec Memory Limit: 162 MB Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一 ...

  9. Java并发/多线程系列——线程安全篇(1)

    创建和启动Java线程 Java线程是个对象,和其他任何的Java对象一样.线程是类的实例java.lang.Thread,或该类的子类的实例.除了对象之外,java线程还可以执行代码. 创建和启动线 ...

  10. [Tjoi2013]循环格

    [Tjoi2013]循环格 2014年3月18日1,7500 Description Input 第一行两个整数R,C.表示行和列,接下来R行,每行C个字符LRUD,表示左右上下. Output 一个 ...