ES6

let,const

函数内部的块级作用域,不允许重复声明,不存在变量提升,声明在全局也不具有全局属性(不可用window.访问)
const只读常量,一旦声明无法改变(只能保证引用类型地址不变,不能保证地址数据不变,使用Object.freeze({...})返回冻结对象)
var a = [];
for(let i = 0; i<10; i++){
a[i] = function(){console.log(i)};
}
a[1](); //1 此方法可以取代闭包的存值方案

解构赋值

按照一定模式,从数组和对象中提取值,对变量进行赋值
数组解构:

let [a,b,c] = [1,2,3];
 //默认值在等号右边相应数据===undefined生效
let [foo = 6] = [];

对象解构:

let {foo,baz} = {foo:"a", baz:"b"};
let {msg = 6} = {}; //指定默认值

字符串解构:

let [a,b] = 'hello';

数值,布尔值解构(匹配等号右边对象.toString方法):

let {toString:str} = true;
alert(str === Boolean.prototype.toString); //true

函数参数解构赋值:

function fun({x=0,y=0}){alert(x)};
fun({x:1,y:2}); //1

函数参数

function fun(height = 0){}

参数解构赋值+默认参数,设置默认参数后arguments.length=参数总数-默认参数数

function fun({x, y=0}, z=0){console.log(x,y,z)};
fun({x:0, y:1}, 2); //0 1 2
fun({x:0}); //0 0 0

REST参数(是Array实例)

将逗号分隔的参数序列转换为数组参数

function fun(...params){
  console.log(params);
};
fun(1,2,3); //[1,2,3]

扩展运算符

REST参数逆运算,数组转为逗号分隔的参数序列

let a1 = [1];
let a2 = [2, 3];
let a3 = [...a1, ...a2]; // [1, 2, 3]
fun(...a3); // fun(1, 2, 3)

模板字符串

let n = 6;
let name = \`hello ${n}\`;
//${fun()}内可以调方法返回值

多行字符串(避免+拼接)

let r = \`hello
  world\`;

标签模板,跟函数名后,字符有变量,被处理成多个参数
可用于过滤参数值,实现安全Html

let a = 1;
let b = 2;
function tag(...values){};
tag\`hello ${a} world ${b}\`; //tag(['hello', 'world', ''], 1, 2);

Symbol

新增数据类型,表示独一无二的值

//参数只是表示对当前Symbol值的描述,Symbol返回的值各不相同
let s1 = Symbol('sss'); 

意义:对象属性名都是字符串,一种机制保障每个属性名独一无二,防止属性名冲突,可结合Class实现私有方法

箭头函数

//只有单条语句可以省略retun xxx;
let f = () => 6;
f(); //6

同普通函数区别
1.this指向固定化,因为箭头函数没有自己的this, 内部this指向定义时的外围作用域
2.不能用作构造函数(不可new)没有construct, prototype
3.函数内部不可使用arguments(可REST参数替代),super, new.target
4.不可以使用yield,不能作为Generator函数
5.无法使用call(), apply(), bind()改变this指向

var obj = {
  say:function(){
    setTimeout(() => {
      console.log(this); //obj
    });

    setTimeout(function(){
      console.log(this); //window
    })
  },
  f:()=>{
    console.log(this); //window
  }
}
obj.say();

尾调用

某函数最后一步调用另一个函数并返回该函数

function A(x){
  return B(x);
}

尾调用优化
尾调用是函数最后一步,不需要保留外层函数调用帧,只保留内层函数调用帧,节约内存,ES6尾调用优化只在严格模式下开启(禁用arguments, caller,因为尾调用优化会改写调用栈,导致以上变量失真)

function f(){
  let m = 1;
  let n = 2;
  return g(m+n);
};
f();
//以上等同,删除f(外层函数调用帧),只保留g(内层函数调用帧)
g(3);

Generator函数

ES6提供的异步编程解决方案,最大特点可以交出函数执行权
整个Generator函数是一个异步任务的容器,异步操作需要暂停的地方用yield语句注明

let readFileAsync = function (name) {
    return new Promise(function (resolve, reject) {
        setTimeout(()=> {
            resolve({name});
        }, 1000);
    });
};

function* gen() {
    console.log('-------------gen start-------------');
    yield readFileAsync('66');
    yield readFileAsync('77');
    console.log('-------------gen end-------------');
};

let g = gen();
console.log('-------------out-------------');
let f1 = g.next();//{done:false, value:Promise}
f1.value.then(function (data) {
    console.log(data);
    return g.next().value;//{done:false, value:Promise}
}).then(function (data) {
    console.log(data);
    //{done:true, value:null},如注销这一步end不会输出,说明函数停在yield上未往下执行
    g.next(); 
});
// out -> gen start -> 66 -> 77 -> gen end

Async

Generator函数语法糖

async function gen() {
    console.log('-------------gen start-------------');
    //await暂停直到promise返回,才开始执行下一个
    await readFileAsync('66').then((data)=> {
        console.log(data);
    });
    await readFileAsync('77').then((data)=> {
        console.log(data);
    });
    console.log('-------------gen end-------------');
}
//async语法无需调用next()
gen();
console.log('-------------out-------------');
//gen start -> out -> 66 -> 77 -> gen end

Set和WeakSet

Set新数据结构,类似数组,成员值唯一,可用于数组去重复

const s = new Set([1, 1, 2]);
//add, delete, has, clear, size
s.add("2");
//keys(), values(), entries(), forEach()
//因为Set结构没有key值只有value所以keys,values方法行为一致
for (let item of s.keys()) {
    console.log("set:" + item);//输出:1,2,"2"
}
for (let item of s.values()) {
    console.log("set:" + item);//输出值:1,2,"2"
}
for (let item of s.entries()) {
    console.log(item);//输出:[1, 1],[2, 2],["2", "2"]
}
for (let item of s) {
    console.log(item);//输出:1,2,"2"
}
//输出:1:1,2:2,"2":"2"
s.forEach((value, key)=>console.log(key + ":" + value));

WeakSet同Set,但每个成员都必须是对象,无size属性不能遍历,无clear,成员弱引用,随时可能消失

let a = [[1], [2]];
const ws = new WeakSet(a);
//add, delete, has
ws.add({});
//let b = [1,2];
//Error,因为WeakSet要求b中每个成员是对象1,2是值
//const ws = new WeakSet(b);

Map和WeakMap

Map类似键值对集合(Hash),键的范围不限制于字符串,各类型值都可当键
Object结构提供了“字符串-值”,Map结构提供“值-值”

const m = new Map();
const k = {key: 66};
//set, get, delete, has, clear, size
m.set(k, 'content');
const m2 = new Map([['key1', 'value1'], ['key2', 'value2']]);
//keys(), values(), entries(), forEach()
for(let key of m2.keys()){
    console.log(key);//输出:key1, key2
}
for(let value of m2.values()){
    console.log(value);//输出:value1, value2
}
for(let [key, value] of m2.entries()){
    console.log(key, value);//输出:key1, value1, key2, value2
}
//同上
for(let [key, value] of m2){
}
const reporter = {
    report: function(){
        return "66 say:";
    }
}
//支持forEach,添加第二个参数,用来绑定this
m2.forEach(function(value, key, map){
    console.log(this.report(), key, value);
}, reporter);

WeakMap同Map,但只接受对象作键名(null除外),无size属性不能遍历,无clear,成员弱引用,随时可能消失

WeakSet, WeakMap用途主要是实例弱引用,删除实例,它们自己也随之消失,不会造成内存泄漏

Iterator(本质指针)

便利器,一种接口,为不同数据结构提供统一访问机制,任何数据结构只要部署Iterator接口,就可遍历,Iterator主要供for...of消费
遍历过程:
1.建立一个指针,指向数据结构起始位
2.第一次调用next(),指针指向数据结构第一个成员(包含value,done属性的对象)
3.第二次调用next(),指针指向数据结构第二个成员
...
具备Iterator接口的数据结构:Array, Map, Set, String,Arguments等

for ... of 循环

Proxy

在目标对象之前假设一层拦截,元编程,对编程语言的编程

//对一空对象假设拦截,重定义属性get行为
var obj = new Proxy({}, {
  get:function(target, property){
    return 66;
  }
});
obj.time //66

WeakSet类似Set, 不重复值集合,但成员只能是对象,不能遍历,因为成员都是弱引用

Reflect

let obj = {foo:1};
//1查找并返回目标对象obj的foo属性值
Reflect.get(obj, 'foo'); 

本质上是ES5语法糖,prototype属性依然存在, 类的所有方法都定义在prototype上,必须调用new创建实例,内部不存在变量提升
类方法内部如果含有this,默认指向类实例

class Point {
  _x; //私有属性

  //new命令生成对象实例自动调用该方法
  //不显示定义,默认加个空constructor方法
  //默认返回this实例对象
  constructor(x = 0){
    //实例属性除非显示定义在其本身(this)上
    //否则都是定义在原型上
    this.x = x;
    this._x = x;
    _x = x;

    //构造函数不是通过new命令掉,可以用来确定构造函数如何调用
    if(new.target !== undefined){
    }
  }

  //方法不用加function关键字修饰
  toString(){
    return this.x;
  }

  //静态方法,不被实例继承,只有类调用Point.hello()
  //如果静态方法包含this,这个this指类(Point)而非实例对象
  static hello(){}

  get x(){
    return _x;
  }

  set x(v){
    _x = v;
  }
}

等同
Point.prototype = {constructor(){}, toString(){}}

类实现私有方法(ES6不支持):
1.命名加_
2.将私有方法移到类定义外
3.利用Symbol值唯一,将私有方法命名为一个Symbol让外界取不到

类继承 extends

class ColorPoint extends Point{
  constructor(x, color){
    //子类必须调用super后才能调用this,先创造父类实例对象
    super(x); 
    this.color = color;
  }

  toString(){
    return this.color + ' ' + super.toString();
  }
}

Module

ES6模块通过export显示指定输出代码,通过import命令输入

export {m, moon as n}
let m = 1;
let moon = 2;
//不使用export default,用户要知道所加载的变量名,函数名
import {m, n} from 'fs';
//使用export default到处模块,import可以取任意名字
export default function(){};
import lulu from 'fs';

模块整体加载

export function a(){}
export function b(){}
import {a,b} from 'xxx';
import * as all from 'xxx';

export和import复合写法

export {a, b} form 'xxx';
export * from 'xxx';
export {default} from 'xxx';

ES6模块与CommonJS模块
1.CommonJS模块输出值拷贝,ES6模块输出值引用
2.CommonJS模块运行时加载,ES6模块编译时输出接口

ES6输入的模块变量,只是一个“符号链接”,只读,不能重新赋值

export let obj = {};

import {obj} from 'xxx';
obj.prop = 66; //ok
obj = {}; // error

Promise

代表一个异步操作,有3种状态:pending,fulfilled,rejected
Promise构造函数是同步执行,then里的回调函数是异步
Promise状态只能从pending->fulfilled或pending->rejected,且状态只能变更1次,不能再变更
Promise的then,catch方法会返回一个新Promise实例
Promise的then,catch抛出错误被后续捕获,请
return Promise.reject(new Error('error'));
throw new Error('error');
缺点:
1.一旦创建,无法取消,
2.不设置回调,内部抛出错误,不会反应到外部
3.处于pending状态,无法得知目前进展

let p = new Promise(function(resolve, reject){
  //...Promise
  if( /*异步操作成功*/){
    resolve(value);
  }
  else{
    reject(error);
  }
});
//then方法接受2个回调
p.then(function(value){}, function(error){})
  .catch(function(error){});

//等全部状态改变
let ps = Promise.all([p1, p2]);
//一个状态改变
let ps = Promise.race([p1, p2]);

//将现有对象转化为promise,并设为resolve
let p = Promise.resolve($.ajax('/dddd.json'));
//将现有对象转化为promise,并设为reject
let p = Promise.reject('error');

done():Promise对象回调链,无论then,catch结尾,最后一个方法抛出错误,都无法捕捉,提供一个done方法处于回调链尾,保证任何可能出的错误

finally():不论Promise对象最后状态成功失败都执行的操作

*** done和finally并为包含在ES6的Promise中

try():不区分执行函数是同步或异步,统一用Promise包装处理,用then指定下一步流程,用catch方法处理抛出错误

Promise.prototype.finally = function (callback) {
    let P = this.constructor;
    return this.then(
            value  => P.resolve(callback()).then(() => value),
            reason => P.resolve(callback()).then(() => {
            throw reason
        })
    );
};

Promise.prototype.done = function (onFulfilled, onRejected) {
    this.then(onFulfilled, onRejected)
        .catch(function (reason) {
            // 抛出一个全局错误
            setTimeout(() => {
                throw reason
            }, 0);
        });
};

function runAsync1() {
    let p = new Promise(function (resolve, reject) {
        console.log('begin 1');
        setTimeout(()=> {
            resolve('data 1');
        });
    });

    return p;
};

function runAsync2() {
    let p = new Promise(function (resolve, reject) {
        console.log('begin 2');
        setTimeout(()=> {
            resolve('data 2');
        });
    });

    return p;
};

function runAsync3() {
    let p = new Promise(function (resolve, reject) {
        console.log('begin 3');
        setTimeout(()=> {
            resolve('data 3');
        });
    });

    return p;
};

runAsync1()
    .then((data)=> {
        console.log(data);

        return runAsync2();
    })
    .then((data)=> {
        console.log(data);

        return runAsync3();
    })
    .finally(()=> {
        console.log("finish");
    })
    .done(()=> {
        console.log("all success");
    });

简单手写Promise原理

function Defer(executor) {
    var self = this;
    self.status = 'pending';
    self.data = undefined;
    self.onResolvedCallback = [];

    function resolve(value) {
        if (self.status === 'pending') {
            self.status = 'resolved';
            self.data = value;
            for (let i of self.onResolvedCallback) {
                self.onResolvedCallback[i](value);
            }
        }
    }

    try {
        //执行异步方法
        executor(resolve);
    }
    catch (e) {
    }
};

Defer.prototype = {
    constructor: Defer,
    //then返回Defer对象
    then: function (onResolved) {
        var self = this;
        var promise2;

        if (self.status === 'resolved') {
            return promise2 = new Defer(function (resolve) {
                try {
                    var x = onResolved(self.data);
                    if (x instanceof Defer) {
                        x.then(resolve);
                    }

                    resolve(x);
                }
            });
        }

        if (self.status === 'pending') {
            return promise2 = new Promise(function (resolve) {
                self.onResolvedCallback.push(function (value) {
                    try {
                        var x = onResolved(self.data);
                        //返回值为Promise
                        if (x instanceof Defer) {
                            x.then(resolve);
                        }
                    }
                });
            });
        }
    }
};

var d = new Defer(function (resolve) {
    setTimeout(function () {
        resolve({a: 0});
    }, 1000);
});

d.then(function (data) {
    alert(data);
});

ES6严格模式:
1.变量必须声明后使用
2.函数参数不能同名属性
3.不能用with
4.禁止this指向全局
5.不能使用arguments.callee,arguments.caller
6.增加protected, static, interface关键字

你可能感兴趣的:(ES6)