ES6新特性简介

ES6新特性简介

环境安装

npm install -g babel
npm install -g babel-node  //提供基于node的REPL环境
//创建 .babelrc 文件
{"presets": ["es2015"]}
npm install babel-presets-es2015

箭头函数和词法this

箭头函数的用法类似phython, coffeeScriptjava8

//expression func body, (仅有1参数 括号可省略)
var odds = evens.map(v => v+1);
var nums = evens.map((v,i) => v + i);

//statement func body
nums.forEach( v => {
    if(v % 5 === 0){
        fives.push(v);
    }
});


//lexical this
var sindy = {
    name: 'Sindy',
    friends: ['nami', 'robin'],
    printFriends() {
        //sindy.printFriends() this指向sindy,
        //forEach迭代函数内部this,跟它定义的上下文this一致
        this.friends.forEach(f=>{
            console.log(this.name + ' knows ' + f);
        });
    }
};

类和继承

classextend 是一种语法糖,也是基于原型继承实现的。
class支持 super calls, 实例化,静态方法和构造函数。

class关键字 声明类

//class声明类 内部直接是属性和方法 不用,分隔。 constructor
class Person{
  constructor(name, age){
    this.name = name;//实例属性
    this.age = age;
    
  }
 
 sayhi(name){//原型对象的方法
   console.log(this.name+' say hello to ' + name);
 }
 
 static like(){//静态方法
   console.log('i want to be freedom king');
 }
}

extends关键字 声明继承

//继承关键字 extends
class Zoro extends Person{

  constructor(fav){
    super('zoro', 18); //constructor中, super引用父类的构造函数

    this.fav = 'keep going';

    // console.log(super); //error 不能直接打印super 
    console.log(super('cici',9),'<--c');

  }
  
  sayhi(){
    // console.log(super); //error 不能直接打印super
    console.log(super.sayhi(),'<--m'); //原型对象的方法中, super引用父类的原型对象
    
    super.sayhi();//调用父类原型对象的方法
  }
}

增强的对象字面量

书写对象字面量更方便简洁。 如:foo:foo的简写, 函数定义简写, 动态属性名。

var obj = {
    __proto__: theProtoObj, //设置原型对象
    ['__proto__']: somethingElse, //['__proto__']表示计算的属性名,不会认为是设置原型对象, 有时也可避免提早报同名属性的错误
    handler,  // hanlder: handler 的简写
    toString(){//类似定义类 命名函数表达式的名称作为key
        //super calls
        return 'd' + super.toString(); //super 应该指向 theProtoObj
    },
    ['prop_'+(()=>23)]: 23 //[expression] 中括号表示内部为属性名的计算表达式,可实现动态属性名
}

__proto__属性在node下都支持,但在浏览器环境不一定都支持, chrome是支持的。

模板字符串

模板字符串跟php双引号字符串类似 "hello ,$name",字符串中可以解析变量和语句, 对于构造字符串是很方便的。

//单行
`this is an alone night`

//多行
`In ES5 this is
not legal`

//变量插值
var name = 'idle', time='today';
var greeting = `hello ${name}, how are you ${time}`;

//不转义
String.raw`in es5 "\n" is a line-feed`

解构

参数解构 对象解构 数组解构, 解构是一种十分方便的语法特性. 当结构不对应解析失败时,会对应的返回undefined,不报错.

//解构赋值
var [a, b] = [1,2]; // a===1, b===2

var {name, age}  = getPerson();

//参数解构
function hello({name: x}){
    console.log('hello, ', x);
}
hello({name: 'alice'});

//解构失败
var [a] = []; // a===undefined

//提供解构失败时的默认值
var [a=1] = []; //a===1 

//参数解构失败的默认值
function r({x,y,w=10,h=20}){
    return x+y+w+h;
}
r({x:1, y:2});

//参数默认值
function f(a, b=10){
    return a+b;
}
f(5);

//rest arguments
function f(x,...y){//剩余形参
    // y is an array
    return x * y.length
}

f(3, 'hello', true);//6

function f(x,y,z){
    return x+y+z;
}

f(...[2,3,4]); //=>9 剩余实参

块级作用域

letconst 声明的变量和常量都是属于块级作用域的.

function f(){
    let x;
    {
        const x = 'sindy'; //ok 因为块级作用域
        x = 'foo'; //error 因为x是常量
    }
    x = 'bar'; //在let 之后赋值,没问题
    let x = 'inner'; //error 重复声明
}

迭代对象(iterator) 和 for .. of ..

迭代对象允许自定义迭代方式,如:

let fibonacci = {
    [Symbol.iterator]() {
        let pre=0, cur=1;
        return {//返回包含next方法的迭代对象(iterator)
            next(){
                [pre, cur] = [cur, pre+cur];
                return {done: false, value: cur}; //iteratorResult
            }
        }
    }
};

for(var n of fibonacci){
    if(n>100){//若无终止条件会一直迭代下去 n应该代表的是每次迭代的结果
        break;
    }
    console.log(n);
}

//typescript风格的iterator接口定义
interface IteratorResult{
    done: boolean,
    value: any
}

interface Iterator {
    next(): IteratorResult //包含next方法,且next()返回IteratorResult类型结果
}

interface Iterable {
    [Symbol.iterator](): Iterator // fibonacci() 执行后返回Iterator
}

生成器generators

function*yield, function*声明的函数返回一个generator实例. generator是iterator的子类型,它包含自己的thrownext

generator可以实现await风格的异步编程

//generator版的fibonacci
var fibonacci = {
    [Symbol.iterator]: function*() {//function*声明
        var pre=0, cur=1;
        for(;;){//不会终止的循环?
            var temp = pre;
            pre = cur;
            cur += pre;
            yield cur;//generator实例每次执行都从yield的地方重新开始?
        }
    }
};

for(var n of fibonacci){
    if(n > 100){
        break;
    }
    console.log(n);
}

//typescript风格的generator接口定义
interface generator extends iterator {
    next(value?: any): IteratorResult; //next方法可带参数, yield返回参数给next?
    throw(exception: any); 
}

注意 iterator and generator 目前需要polyfill才能使用, 新版的chrome已支持.

unicode的完全支持

// same as ES5.1
"?".length == 2

// new RegExp behaviour, opt-in ‘u’
"?".match(/./u)[0].length == 2

// new form
"\u{20BB7}" == "?" == "\uD842\uDFB7"

// new String ops
"?".codePointAt(0) == 0x20BB7

// for-of iterates code points
for(var c of "?") {
  console.log(c);
}

模块(modules)

ES6有不同于amdcmd 的模块风格

//>lib/math.js
export function sum(x,y){
    return x + y;
}

export var fnum = 3.122323;

//>app.js
import * as math from 'lib/math';
console.log(math.sum, math.fnum);

//>other.js
import {fnum, sum} from 'lib/math'; //对象解构赋值
console.log(fnum, sum);

一些额外的特性 export defaultexport *

//>lib/otherMath.js
export * from 'lib/math'; //导出math.js的接口
export var e = 2.323;
export default function(x){
    return Math.exp(x);
}

//>app.js
import exp, {sum , e} from 'lib/otherMath';

模块导出 export

var name = 'sindy';
var age = 20;

//相当于node  module.exports = {name:name, age:age};
export {name, age};

//相当于module.exports.default = function getName(){..}
export default function getName(){
    return name;
}

模块导入 import

//import m from './modA';  m === modA.export.default

//import {name, age} from './modA' modA.exports 析构

import getName, {name, age} from './module-e.es';

console.log(name, age);
console.log(getName());

Map , Set, WeakMap, WeakSet

//Sets
var s = new Set();
s.add('hello').add('goodbye').add('hello');//已有则不再加入
s.size === 2; //true

//Maps
var m = new Map();
m.set('hello', 'good');
m.set(s, 23);
m.get(s) === 23;

//WeakMap
var wm = new WeakMap();
wm.set(s, {extra:24});
vm.size === undefined;

//WeakSet
var ws = new WeakSet();
ws.add({data:12});

proxies

拦截或代理对象的属性读写,函数的调用。

//proxy a normal object
var target = {};//被代理的对象
var handler = {//代理哪些方法
    get: function(reciever, name){//get代理对属性的访问
        return `hello, ${name}`;
    }
};
var p = new Proxy(target, handler);
p.world === 'hello, world';

//proxy a function object
var target = function(){ console.log('i am the target'); };
var handler = {
    apply: function(reciever,...args){//代理 target()
        console.log('i am the proxy');
    }
};


//代理的类型
var handler = {
    //target.prop
    get: ...,
    //target.prop = val
    set: ...,
    //prop in target
    has: ...,
    //delete target.prop
    deleteProperty: ...,
    //target(args)
    apply: ...,
    //new target(args)
    constructor: ...,
    //Object.getOwnPropertyDescriptor(target, prop)
    getOwnPropertyDescriptor: ...,
    //Object.defineProperty(target, prop, descriptor)
    defineProperty: ...,
    //Object.getPrototypeOf(target), target.__proto__
    //obj.isPrototypeOf(target), obj2 instanceof target
    getPrototypeOf: ...,
    //Object.setPrototypeOf(target, proto)
    setPrototypeOf: ...,
    //for(var i in target)
    enumerate: ...,
    //Object.keys(target)
    ownKeys: ...,
    //Object.preventExtensions(target)
    preventExtensions: ...,
    //Object.isExtensible(target)
    isExtensible: ...
}

标识符 symbol

(function(){
    //module scope symbol
    var key = Symbol('key');

    function MyClass(privateData){
        this[key] = privateData;
    }
    MyClass.prototype = {
        dostuff: function(){
            ...this[key]..
        }
    };

    typeof key === 'symbol';
})();

var c = new MyClass();
c['key'] === undefined;

内置的子类

Array , DateElement等成为内置的子类。

class MyArray extends Array{
    constructor(...args){
        super(...args);
    }
}

var arr = new MyArray();
arr[1] = 12;
arr.length === 2;

Math + Number + String + Object API扩展

Number.isInterger(Ifinity); //false
Number.isNaN('NaN'); //false

Math.hypot(3,4); //5

'abcde'.includes('abc');
'abc'.repeat(2);

Array.from(document.querySelectAll('h2')); //return a real array
Array.of(1,2,3); => [1,2,3] 枚举数组元素的形式 创建数据, 同 new Array(1,2,3); 但没有仅有1各参数时的歧义
[0,0,0].fill(7,1); //从index==1开始填充7
[1,2,3].findIndex(x=>x==2); //返回使迭代器为真的元素的索引
['a','b','c'].entries(); //iterator [0,'a'], [1,'b'], [2, 'c']
['a','b','c'].keys(); //iterator 0,1,2
['a','b','c'].values(); //iterator 'a','b','c'

var alice = {name: 'Alice'};
Object.assign(alice, {age: 18}); //类似extend

二进制和八进制字面量

0b111110111 === 503
0o767 === 503

Promises

Promise是一个异步编程的库,存在于很多其他的JS库中

function timeout(duration = 0){
    return new Promise((resolve, reject) => {//返回稍后将被resolve的promise对象
        setTimeout(resolve, duration);//定时resolve这个新new的promise
    });
}

var p = timeout(1000).then(()=>{//promise链
    return timeout(2000);
}).then(()=>{
    throw new Error('test');
}).catch(err=>{
    return Promise.all([timeout(100), timeout(200)]);
});

反射API(Reflect API)

var o = {a: 1};
Object.defineProperty(o, 'b', {value:2});
o[Symbol('c')] = 3;

Reflect.ownKeys(o); //['a','b',Symbol(c)]

function C(a,b){
    return this.c = a + b;
}
var instance = Reflect.construct(C, [10,12]);
instance.c === 22;

尾调用 tail calls

防止stack overflow

function factorial(n, acc=1){//阶乘计算
    'use strict';
    if(n <= 1){ return acc; }
    return factorail(n-1, n*acc);
}

factorail(10000); //尾调用优化后不会 stack overflow

转载于:https://www.cnblogs.com/stephenykk/p/5616717.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值