鉴于最近用 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); // 5

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

2.2 es6 作用域的来袭

先看个例子:

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

函数体内部定义了一个块作用域,其上级作用域就是函数体,当在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()

原博客:http://www.cnblogs.com/stitchgogo/p/7533273.html

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

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

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

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

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

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

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

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

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

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

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

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

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

  7. ES6入门笔记

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

  8. 读阮一峰对《javascript语言精粹》的笔记,我有疑问。

    <javascript语言精粹>是一本很棒的书籍,其中作者在附录列出了12种他所认为的javascript语言中的糟粕. 我最近开始跟读前端前辈的博客,其中读到了阮一峰的<12种不宜 ...

  9. 监控阮一峰老师的blog

    引言 阮一峰大家基本都认识,很厉害的一个人,经济学博士,文章写得很棒,知识面很广泛,计算机.算法.英语.文采,这是能想到的他的一些标签,他的博客应该算是最受欢迎的博客之一了. 我经常回去看他的博客,但 ...

随机推荐

  1. Altium Designer XX 重新定义板框形状和大小的方法

    Altium Designer15 重新定义板框形状和大小的方法:重新定义板框形状和大小的方法.很简单,点击数字键"1",就会看到板框界面变绿了这时候你在去点击菜单栏里的Desig ...

  2. java语言实现的短信接入实例,各公司大同小异

    和几家短信平台接触过,都进行了接入测试.总体来说短信发送又快,覆盖率又全的,价格相对贵些.简易选两家分开使用,短信验证码的用一家贵的快的,普通的推广群发短信就用一个便宜的. 下面显示下测试代码 pub ...

  3. webdriver(python)学习笔记六——操作测试对象

    定位到具体对象后,就需要对其进行操作,比如点击.输入内容等. 一般来说,webdriver中比较常用的操作对象的方法有下面几个 click 点击对象 send_keys 在对象上模拟按键输入 clea ...

  4. ubuntu11.10(TQ210)下移植boa服务器

    平台:ubuntu11.10 一.下载源码包www.boa.org   boa-0.94.13.tar.gz 二.解压,在其src目录下生产makefile #tar xvfz  boa-0.94.1 ...

  5. JQuery hover鼠标变换

    一般而言,我们为非按钮.链接等元素添加hover事件时,虽然能够处理悬停事件,但是鼠标却并没有变化,会造成悬停事件不明显的结果,为此,我们可以添加CSS样式cursor:pointer,使得该元素的悬 ...

  6. JAVA基础第九组(5道题)

    41.[程序41] 题目:海滩上有一堆桃子,五只猴子来分.第一只猴子把这堆桃子凭据分为五份,多了一个,这只猴子把多的一       个扔入海中,拿走了一份.第二只猴子把剩下的桃子又平均分成五份,又多了 ...

  7. Android Handler机制剖析

    android的handler机制是android的线程通信的核心机制 Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃. Android中的实现了 接收消息的& ...

  8. c/c++ 继承与多态 文本查询的小例子(非智能指针版本)

    问题:在上一篇继承与多态 文本查询的小例子(智能指针版本)在Query类里使用的是智能指针,只把智能指针换成普通的指针,并不添加拷贝构造方法,会发生什么呢? 执行时,代码崩掉. 分析下面一行代码: Q ...

  9. 运维工具pssh和pdsh安装和使用

    1. pssh安装与使用 1.1 pssh安装 [root@server]# wget http://peak.telecommunity.com/dist/ez_setup.py [root@ser ...

  10. ECharts JS应用:图表页面实现

    因为要统计数据进行图表展示,所以就简单学习了 ECharts JS 的应用.它是一个纯Javascript图库,它依赖于一个轻量级的Canvas库 ZRender,并提供直观.生动.交互式和高度可定制 ...