鉴于最近用 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. 201521123055《Java程序设计》第1周学习总结

     1. 本章学习总结 (1)JAVA环境配置(JDK,JVM) (2)编写简易程序熟练代码结构  2. 书面作业 1.为什么java程序可以跨平台运行?执行java程序的步骤是什么? JAVA程序需要 ...

  2. 201521123042《Java程序设计》第13周学习总结

    本次作业参考文件 正则表达式参考资料 1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.bai ...

  3. 201521123030 《Java程序设计》 第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 常用异常 1.题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己 ...

  4. LINUX - awk命令之NF和$NF区别 (转)

    NF和$NF 区别问答:(转)1.awk中$NF是什么意思?#pwd/usr/local/etc~# echo $PWD | awk -F/ '{print $NF}'etcNF代表:浏览记录的域的个 ...

  5. 磁盘管理之inode与block

    索引式文件系统 什么是inode? Inode其实就是索引号,便于我们寻找我们文件所存储的数据块block,索引式文件系统在查找信息,读写操作上都比原来的文件系统要快,我们可以通过inode中记录的b ...

  6. Struts2标签:checkboxlist

    参考自博文:http://www.blogjava.net/koradji/articles/307399.html 语法: <s:checkboxlist name="" ...

  7. temp-mootools简单语法

    // mootools // auditFlag = $(this).getElement('>td input[id="auditFlag"]').val() // .ge ...

  8. 理解G1垃圾回收日志

    本篇文章主要介绍在-XX:+PrintGCDetails选项的情况下G1 GC log打印的信息.(注:本文假设读者对G1算法的基本原理已经有所了解) 下面是一段G1垃圾收集器相关的log信息 0.5 ...

  9. 异常处理第一讲(SEH),筛选器异常,以及__asm的扩展,寄存器注入简介

    异常处理第一讲(SSH),筛选器异常,以及__asm的扩展 博客园IBinary原创  博客连接:http://www.cnblogs.com/iBinary/ 转载请注明出处,谢谢 一丶__Asm的 ...

  10. 02.python基础知识_02

    数据类型 1.整型 2.布尔值 3.字符串 4.列表 5.字典 6.集合 1.int(整型) i = 2 print(type(i)) 输出:<class 'int'> 2.bool(布尔 ...