ES6(简)

  

一、 let、const 和 var

let和const只在当前块级作用域中有效
const用来声明常量
var是全局作用域有效的

constants.js 模块
export const A = 1;
export const B = 3;
export const C = 4;

test1.js 模块
import * as constants from './constants';
console.log(constants.A); // 1
console.log(constants.B); // 3

test2.js 模块
import {A, B} from './constants';
console.log(A); // 1
console.log(B); // 3

全局对象的属性 (下面是等价的)
window.a = 1
var a = 1
global.a = 1
二、 解构赋值: ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)

如: var [a, b, c] = [1, 2, 3];
    a = 1
    b = 2
    c = 3
    
    let [head, ...tail] = [1, 2, 3, 4];
    head // 1
    tail // [2, 3, 4]

    let [x, y, ...z] = ['a'];
    x // "a"
    y // undefined
    z // []
    

如果等号的右边不是数组,那么就会报错
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

ES6内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组的员不严格等于undefined,默认值是不会生效的
var [x = 1] = [undefined];
x // 1

var [x = 1] = [null];
x // null

对象解构赋值中如果变量名与属性名不一致,必须写成下面这样
下面真正被赋值的是baz
var { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined  foo是模式

let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

解构赋值的规则是,只要等号右边的值不是对象,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError

注: 模式不能带有圆括号
三、字符串的扩展

模板字符串, 用反引号标示普通字符串或者多行字符串, 使用反引号需要加反斜杠
传统的写法
$("#result").append(
"There are <b>" + basket.count + "</b> " +
"items in your basket, " +
"<em>" + basket.onSale +
"</em> are on sale!"
);
模板字符串写法
$("#result").append(`
There are <b>${basket.count}</b> items
in your basket, <em>${basket.onSale}</em>
are on sale!
`);
四、数组的扩展

Array.from() 将类数组转换成数组
Array.from('hello')
// ['h', 'e', 'l', 'l', 'o']

Array.of() 将一组值转换为数组
Array.of(3, 11, 8) // [3,11,8]

只有当参数个数不少于2个时,Array()才会返回由参数组成的新数组。参数个数只有一个时,实际上是指定数组的长度
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]
五、函数的扩展

rest参数,获取函数多余的参数
function add(...values) {
    
    let sum = 0;
    
    for (var val of values) {
        
        sum += val;
    }
    
    return sum;
}
add(2, 5, 3)  // 10

扩展运算符(...), 将一个数据转为用逗号分隔的参数序列
function add(x, y) {
return x + y;
}

var numbers = [4, 38];
add(...numbers) // 42

替代数组的apply方法 : 由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了
// ES5的写法
function f(x, y, z) {
// ...
}
var args = [0, 1, 2];
f.apply(null, args);

// ES6的写法
function f(x, y, z) {
// ...
}
var args = [0, 1, 2];
f(...args);

箭头函数都没有自己的this, this表示的是最外层的

:: 双冒号左边是对象,右边是函数
六、对象的扩展

Object.is(,) 比较2个值是否严格相等,与(===)行为基本一致
不同之处为:Object.is的 +0不等于-0, Nan等于自身

Object.assign 用于对象的合并,同名后面的会覆盖前面  是浅拷贝,而不是深拷贝
var obj1 = {a: {b: 1}};
var obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b // 2
七、二进制数组

用ArrayBuffer对象、TypeArray视图和DataView视图操作JS的二进制数据, 直接操作内存数据

ArrayBuffer与字符串的相互转换
// ArrayBuffer转为字符串,参数为ArrayBuffer对象
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}

// 字符串转为ArrayBuffer对象,参数为字符串
function str2ab(str) {
var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
var bufView = new Uint16Array(buf);
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
八、 Set和Map

Set类似数组, 它的成员是唯一的,里面没有重复的值
var set = new Set([1, 2, 3, 4, 4]
set.add(5)
[...set]
// [1, 2, 3, 4, 5]

var items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5

Set的遍历
keys():返回一个键名的遍历器
values():返回一个键值的遍历器
entries():返回一个键值对的遍历器
forEach():使用回调函数遍历每个成员
let set = new Set(['red', 'green', 'blue']);

for ( let item of set.keys() ){
console.log(item);
}
// red
// green
// blue

for ( let item of set.values() ){  // 可以省略values
console.log(item);
}
// red
// green
// blue

for ( let item of set.entries() ){
console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

数组的map和filter方法也可以用于Set了
let set = new Set([1, 2, 3]);
set = new Set([...set].map(x => x * 2));  // [...set].map映射新的结构
// 上面的代码可用: new Set(Array.from(set, val => val * 2)) // Array.from映射新的结构
// 返回Set结构:{2, 4, 6}

let set = new Set([1, 2, 3, 4, 5]);
set = new Set([...set].filter(x => (x % 2) == 0));
// 返回Set结构:{2, 4}

Set结构的实例的forEach方法,用于对每个成员执行某种操作,没有返回值
let set = new Set([1, 2, 3]);
set.forEach((value, key) => console.log(value * 2) )
// 2
// 4
// 6

JS的Object只把字符串当作键 字符串--值, 而Map不限于字符串作键可以是各种类型 值--var m = new Map();
var o = {p: "Hello World"};

m.set(o, "content")
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false

Map结构转数组结构
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);

[...map.keys()]
// [1, 2, 3]

[...map.values()]
// ['one', 'two', 'three']

[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]

[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]
九、Iterator(遍历器): 为各种不同的数据结构提供统一的访问机制,任何部署Iterator接口的数据结构们都有遍历操作

部署Iterator接口: 只有三类结构原生具有Iterator接口数组、类数组对象以及Set和Map
一个对象如果要有可被for...of循环调用的Iterator接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)
class RangeIterator {
constructor(start, stop) {
this.value = start;
this.stop = stop;
}

[Symbol.iterator]() { return this; }

next() {
    var value = this.value;
    if (value < this.stop) {
    this.value++;
    return {done: false, value: value};
    } else {
    return {done: true, value: undefined};
    }
}
}

function range(start, stop) {
    return new RangeIterator(start, stop);
}

for (var value of range(0, 3)) {
    console.log(value);
}

Symbol.iterator方法的最简单实现
var myIterable = {};

myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
};
[...myIterable] // [1, 2, 3]

// 或者采用下面的简洁写法

let obj = {
    * [Symbol.iterator]() {
    yield 'hello';
    yield 'world';
}
};

for (let x of obj) {
    console.log(x);
}
// hello
// world

for...of循环内部调用的是数据结构的Symbol.iterator方法, 是遍历所有数据结构的统一的方法
for...of循环可以代替数组实例的forEach方法
JavaScript原有的for...in循环,只能获得对象的键名,不能直接获取键值。ES6提供for...of循环,允许遍历获得键值
十、 Generator 用来处理异步操作 返回遍历对象 调用next执行yield定义的下一条,返回出对象, 直到value为undefined, done的值为true function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; }

var hw = helloWorldGenerator();
hw.next(); // ()里面可以带参数

利用Generator函数,可以在任意对象上部署iterator接口
function* iterEntries(obj) {
let keys = Object.keys(obj);
for (let i=0; i < keys.length; i++) {
let key = keys[i];
yield [key, obj[key]];
}
}

let myObj = { foo: 3, bar: 7 };

for (let [key, value] of iterEntries(myObj)) {
console.log(key, value);
}

// foo 3
// bar 7
十一、Promise 是异步编程的一种解决方案 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果  三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败) var promise = new Promise(function(resolve, reject) { // ... some code

    if (// 异步操作成功){
    resolve(value);
    } else {
    reject(error);
    }
});

Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数, 第二个函数参数是可选的
promise.then(function(value) {
    // success
}, function(value) {
    // failure
});

示例:
function timeout(ms) {
    return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
    });
}

timeout(100).then((value) => {
    console.log(value);
});

Promise新建后就会立即执行,then方法是在当前脚本所有同步任务执行完成后再执行

Promise对象实现Ajax操作示例:
var getJSON = function(url) {
var promise = new Promise(function(resolve, reject){
    var client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

    function handler() {
    if ( this.readyState !== 4 ) {
    return;
    }
    if (this.status === 200) {
    resolve(this.response);
    } else {
    reject(new Error(this.statusText));
    }
};
});

return promise;
};

getJSON("/posts.json").then(function(json) {
    console.log('Contents: ' + json);
}, function(error) {
    console.error('出错了', error);
});
十二、 异步操作和Async(ES7)

JS异步编程方法:
    回调函数
    事件监听
    发布/订阅
    Promise 对象

async 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里
// 50毫秒后输出“hello world”
function timeout(ms) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}

async function asyncPrint(value, ms) {
    await timeout(ms);
    console.log(value)
}

asyncPrint('hello world', 50);

Async的使用方式
// 函数声明
async function foo() {}

// 函数表达式
const foo = async function () {};

// 对象的方法
let obj = { async foo() {} }

// 箭头函数
const foo = async () => {};

最好把await命令放在try...catch代码
async function myFunction() {
    try {
        await somethingThatReturnsAPromise();
    } catch (err) {
        console.log(err);
    }
}
// 另一种写法
async function myFunction() {
    await somethingThatReturnsAPromise().catch(err => {
        console.log(err);
    };
}

如果希望多个请求并发执行,可以使用Promise.all方法
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
十三、 类: 类的数据类型就是函数,类本身就指向构造函数 //定义类 class Point {

    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    toString() {
        return '(' + this.x + ', ' + this.y + ')';
    }

}

向类添加多个方法
class Point {
    constructor(){
    // ...
    }
}

Object.assign(Point.prototype, {
    toString(){},
    toValue(){}
})

Class之间可以通过extends关键字实现继承
class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
}

class ColorPoint extends Point {
    constructor(x, y, color) {
        this.color = color; // ReferenceError
        super(x, y);
        this.color = color; // 正确
    }
}

子类的__proto__属性,表示构造函数的继承,总是指向父类
子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性

static调用静态方法(类似类方法), 父类的静态方法能被子类继承
class Foo {
static classMethod() {
return 'hello';
}
}

Foo.classMethod() // 'hello'

var foo = new Foo();
foo.classMethod()
// TypeError: undefined is not a function
十四、 Module

export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能

// export命令:
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};

// import命令:
A、
import {firstName, lastName, year} from './profile';
function setName(element) {
    element.textContent = firstName + ' ' + lastName;
}
B、
import * as circle from './circle';
console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));

export default命令 : 一个模块只能有一个默认输出
// export-default.js
export default function () {
console.log('foo');
}
// import-default.js:  import命令可以为该匿名函数指定任意名字 如: customName
import customName from './export-default';
customName(); // 'foo'
欢迎加QQ群交流: iOS: 279096195 React Native: 482205185
原文地址:https://www.cnblogs.com/GeekStar/p/5362163.html