ES6背记手册


如下内容大部分参考自阮一峰的ES6在线教程javascript

ES6新特性一览

  • letconst
  • 暂时性死区
  • 解构赋值
  • 字符串的unicode表示
  • 模板字符串
  • 对象简写属性
  • 函数的默认参数
  • 函数的剩余参数(rest参数)
  • spread操做符
  • 箭头函数
  • 尾调用优化
  • 遍历器
  • for...of...
  • Symbol
  • Map和Set
  • class
  • Promise
  • Generator
  • async await
  • Proxy和Reflect
  • 二进制数组
  • 模块
  • Math、Number、String、Object、RegExp扩展

let和const的异同

相同点html

  • letconst声明的变量,都是块级做用域,都只在其所在的代码块内有效
  • letconst声明的变量,都不存在变量提高
  • letconst声明的变量,都存在临时性死区
  • letconst都不容许在经过一个做用于内重复声明同一个变量
  • letconst都不容许在函数内对参数从新声明
  • letconst声明的变量,都不是顶层对象的属性

不一样点java

  • let声明的是变量,声明后,能够在任意时刻赋值,修改
  • const声明的是常量,声明后必须马上赋值,且之后不容许修改

let和var的异同

相同点react

  • letvar都是声明一个变量
  • letvar声明的变量,都是能够在声明后,任意时刻赋值,修改

不一样点git

  • let无变量提高,var有变量提高
  • let是块级做用域,var是函数级做用域
  • let不可在做用域内重复声明同一个变量,var能够在同一个做用域内声明同一个变量
  • let声明的变量不属于顶层对象的属性,var声明的变量属于顶层对象的属性
  • let存在临时性死区,var不存在临时性死区

其余es6

  1. 在同做用域内,不能同时使用letvar声明同名变量,无论谁先谁后都不行

const的实质

const实际保证的,并非变量的值不能改动,而是变量指向的那个内存地址所所保存的数据不能改变。github

JavaScript中的简单类型数据,好比string, number, boolean, null, undefined,值就保存在变量指向的那个内存地址,而复合类型的数据,变量指向的那个内存地址,保存的是指向实际数据的一个指针。编程

什么是临时性死区

ES6新概念:临时性死区——TDZ——Temporal Dead Zonejson

因为代码(代码块,函数,模块......)中的变量尚未被初始化而不能使用的状况,具体表现为——报错:Uncaught ReferenceError: xxx is not definedlet,const,class都有临时性死区的表现。在ES6以前,若是在变量初始化以前使用变量,并不会报错,只是其值为undefined而已。数组

模板字符串

  1. 模板字符串简化了多行字符串的写法
  2. 模板字符串简化了在字符串中签入变量的写法
  3. 模板字符串中的变量若是没有声明的话,会报错
  4. 模板字符串默认会将字符串转义

ES6中的函数

  1. 函数参数能够设置默认值
  2. 函数参数的默认值是惰性求值
  3. 函数参数设置默认值后build影响函数的length属性:function add(a, b, c=3){} add.length === 2;// true
  4. 在ES6中,若是函数参数使用了默认值、解构赋值、扩展运算符,就不能在函数内部显式指定为严格模式。函数指定默认值后,显式添加use strict,报错:Uncaught SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list
  5. rest参数只能是尾参数
  6. rest参数不计入函数的length属性
  7. rest参数是一个真正的数组,arguments是类数组
  8. 在ES6中,name属性会返回实际的函数名

箭头函数

  1. 函数体内的this就是定义时的对象,而不是使用时的对象
  2. 箭头函数不能够当作构造函数
  3. 箭头函数内部不存在arguments对象,使用...rest参数代替
  4. 箭头函数不能够作Generator函数
  5. 箭头函数没法使用apply,bind,call改变this指向

解构赋值

可解构赋值的:

  • 数组
  • Set
  • 字符串
  • 对象
  • 函数参数
  1. 数组解构赋值:
// a === 12 
// b === 33
const [a, b] = [12, 33];
  1. 数组解构默认值:
// f === 120 
// h === 56
const [f, h = 100] = [120, 56];
  1. 数组解构默认值:
// f === 120 
// h === 100
const [f, h = 100] = [120, undefined];
  1. 对象解构赋值:
// a === 'Pelli' 
// b === 89
const {a, b} = {a: 'Pelli', b: 89};
  1. 对象解构赋值:
// a === 'pelli 
// b === 18 
// c === 'worker'
const {
    myname: a, 
    age: b, 
    job: c
} = {
    myname: 'pelli', 
    age: 18, 
    job: 'worker'
};
  1. 对象解构默认值:
// p === 'ppp' 
// q === 'hello world'
const {p, q = 'hello world'} = {p: 'ppp', q: 'qqqq'};
  1. 解构赋值的默认值需undefined触发,
    • 对于数组来讲,对应位置没有元素
    • 对于对象来讲,没有同名属性
    • 或者将同名属性或元素显式赋值为undefined
  2. 字符串解构赋值:
// a === 'h' 
// b === 'e' 
// c === 'l'
const [a, b, c] = 'hello world';
  1. 函数参数的解构赋值
const args = function(){return arguments;}
const ags = args(3, 4, 5, 6, 12, 2, 3);
// a === 3 
// b === 4 
// c === 5 
// d === 6 
// e === 12
// f = 2
const [a, b, c, d, e, f] = ags;
  1. 解构赋值时,若是等号右边是数值和布尔值,则会先转为对象

解构赋值圆括号

最佳实践:任什么时候候都不要在解构赋值中放置圆括号

如下状况不能使用

  1. 变量声明语句
  2. 函数参数
  3. 赋值语句模式

只有一种状况可使用圆括号

  1. 赋值语句的非模式部分

解构赋值使用场景

  1. 变量交换
  2. 从函数返回多个值
  3. 定义函数参数
  4. 提取json数据
  5. 定义函数参数默认值
  6. 遍历Map结构
  7. 输入模块指定方法

Symbol

  1. Symbol不是构造函数,定义一个Symbol,前不用加new,正确使用方式为: const s = Symbol()
  2. Symbol值做为对象属性名时,只能使用[]方式访问,不能经过点运算符访问属性
  3. Symbol是独一无二的值

Set和Map

  1. Set相似于数组,可是其中的值都是惟一的,不可重复
  2. Set构造函数的参数必须是可遍历的:arguments,string,array,set,map
  3. Set构造函数的参数只有第一个有效(只须要一个参数)
  4. Set的add方法返回的是Set对象,能够链式调用
  5. Map的set方法,返回的是Map对象,能够链式调用
  6. Set内部只能存在一个NaN
  7. Object.is(0, -0); // false,可是,Set内部0-0相等,只能存在一个.
  8. Set内部:两个空对象,空数组,空函数老是不相等
  9. Map数据结构是键值对的集合
  10. Map数据结构的键不只仅能够是字符串,任何数据类型均可以做为键

for...of...循环

  • arguments
  • 数组
  • 字符串
  • Set
  • Map

Promise的特色

  1. Promise对象的状态不受外界影响
  2. Promise对象的状态一旦肯定就不会再改变
  3. Promise对象的状态变化只多是两个结果中的一个:接受或拒绝

Promise的缺点

  1. Promise对象一旦建立,就没法中途取消
  2. 若是不设置回调函数,Promise对象内部抛出的错误不会反映到外部
  3. 当Promise对象处于pending时,没法得知目前的进展在哪个阶段,换一种说法是没法肯定事件的完成度
  4. 代码冗余,相对于回调函数来讲,语义弱化。无论什么操做都是一堆then

Promise对象和其余代码的执行顺序

  1. 当即执行的Promise比外层其余代码后执行
  2. 当即执行的Promise比setTimeout 0先执行

Promise自己并非异步的,Promise中的“异步”特性是由resolve或者reject的执行时机带来的

// 下面几行代码输出顺序为:3,2,1
setTimeout(() => {
    console.log('1');
}, 0);

var p = new Promise((resolve, reject) => {
    resolve('2')
});

p.then((val) => {
    console.log(val, 'promise');
})

console.log('3');

另外的几行代码:

// 下面几行代码输出顺序为:3,1,2
setTimeout(() => {
    console.log('1');
}, 0);

var p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('2')
    }, 0);
});

p.then((val) => {
    console.log(val, 'promise');
})

console.log('3');

Promise对象的写法最佳实践

参考来源:http://es6.ruanyifeng.com/#docs/promise

理由是下面这种写法能够捕获前面then方法执行中的错误(也就是说,catch不只能够捕获到promise被拒绝的状态,也能够捕获前面then方法中的错误),也更接近同步的写法(try/catch)。所以,建议老是使用catch方法,而不使用then方法的第二个参数。

p.then(function(val){}).catch(function(msg){})的写法

var p = new Promise(function(resolve, reject){
    setTimeout(function(){
        var status = Math.random() * 10;

        if(status > 5){
            resolve(status);
        }else{
            reject('失败');
        }
    }, 10000);
});

p.then(function(value){
    console.log(value);
}).catch(function(msg){
    console.log(msg);
});

不推荐的写法以下:

then方法传递两个参数,第二参数是当被拒绝的时候执行的函数

var p = new Promise(function(resolve, reject){
    setTimeout(function(){
        var status = Math.random() * 10;

        if(status > 5){
            resolve(status);
        }else{
            reject('失败');
        }
    }, 10000);
});

p.then(function(value){
    console.log(value);
}, function(msg){
    // 这里只有在promise被拒绝的时候才会执行
    // 若是then方法报错了,这里没法获知
    console.log(msg);
});

Promise的其余一些常识

  • Promise不能直接作函数调用,即不能:Promise()

class的一些常识

  • class能够看作是语法糖,只是让对象原型的写法更加清晰,更像面向对象的编程语言
  • 类的数据类型是函数,类自己指向构造函数
  • 类不能作函数直接调用,必须和new一块儿使用
  • 类没有变量提高
  • 类的全部方法都定义在prototype上面
  • 类内部定义的全部属性都是不可枚举的
  • 类的length属性值是constructor的参数个数(不包括有默认值的参数)

ES6中的NaN

  1. Number扩展,Number.isNaN()
  2. ES6中,window的方法isNaN()是为了保证向下兼容性,在ES6中,建议使用Nunber.isNaN()
  3. Object.is()中,NaNNaN是相等的,Object.is(NaN, NaN) === true
  4. Set中,只容许存在一个NaN

ES6中的模块

  • 模块相关名词:CommonJSAMDCMDUMD,ES6 Module
  • ES6以前的模块规范:CommonJSAMD,CommonJS用于服务器,AMD用于浏览器
  • ES6的模块设计思想是尽可能静态化,使得在编译时就能肯定模块的依赖关系以及输入输出的变量
  • CommonJSAMD模块,都只能在运行时肯定这些东西,好比,CommonJS模块就是对象,输入时必须查找对象属性
  • ES6模块是编译时加载,使得静态分析成为可能
  • ES6模块自动采用严格模式,无论有没有显式声明"use strict;"
  • 在ES6模块中,顶层的this指向undefined
  • 若是A模块引入的模块B是基本类型,A对B从新赋值的话会报错,若是B是引用类型,A对其属性从新赋值, B的属性值会改变,若是别的模块(好比C模块)也引用了B模块,则A对B的属性值修改也会体如今C模块中
  • 最佳实践:不要对引入的模块进行修改
  • 模块中的import有提高效果,会提高到整个模块以前。提高效果的实质是:import命令是编译阶段执行的,编译阶段老是在代码实际运行以前
  • 因为import是静态执行的,不能使用表达式和变量,由于表达式和变量只有在运行时才能获取到结果
  • 若是屡次执行同一条import语句,则只会真正执行一次,不会执行屡次
  • ES6模块中的几个关键语句:import 'react';,import {lodash} from 'lodash';, , import * from 'react', export var a = 12;, const a = 55; export default a;
  • 正是由于export default其实是输出一个名为default的变量,因此不能在export default后面加变量声明语句
  • ES6模块没法动态加载、按条件加载、运行时加载。由于import语句是在编译时执行的,是静态的

CommonJS和ES6模块的不一样

  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
  • Node环境中,ES6 模块之中,顶层的this指向undefinedCommonJS 模块的顶层this指向当前模块,这是二者的一个重大差别。
  • 在Node环境中,如下几个变量在模块中是不存在的:arguments,require,module,exports,__filename,__dirname

ES6模块的运行机制

ES6 模块的运行机制与 CommonJS 不同。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。换句话说,ES6 的import有点像 Unix 系统的“符号链接”,原始值变了,import加载的值也会跟着变。所以,ES6 模块是动态引用,而且不会缓存值,模块里面的变量绑定其所在的模块。


微信公众号:撩码

微信公众号:撩码

相关文章
相关标签/搜索