ES6特性

作者: 熊二不大 | 来源:发表于2017-10-29 13:20 被阅读271次

    箭头函数

    一个速记符号代替function(),但是它不会以相同方式绑定this

    //no-eval
    var odds = evens.map(v => v + 1);  // no parentes and no brackets
    var nums = evens.map((v, i) => v + i);
    var pairs = evens.map(v => ({even: v, odd: v + 1}));
    
    // 花括号申明体
    nums.forEach(v => {
      if (v % 5 === 0)
        fives.push(v);
    });
    

    this指向啥呢?

    var object = {
        name: "Name", 
        arrowGetName: () => this.name,
        regularGetName: function() { return this.name },
        arrowGetThis: () => this,
        regularGetThis: function() { return this }
    }
    
    console.log(this.name)
    console.log(object.arrowGetName());
    console.log(object.arrowGetThis());
    console.log(this)
    console.log(object.regularGetName());
    console.log(object.regularGetThis());
    

    Class类中箭头函数:

    class someClass {
        constructor() {
            this.name = "Name"
        }
    
        testRegular() {
            return function() { return this }
    
        }
    
        testArrow() {
            return () => this.name;
        }
    }
    
    var obj = new someClass();
    
    console.log(obj.name)
    console.log(obj.testRegular()());
    console.log(obj.testArrow()());
    

    Classes

    我们知道是从“真”语言模仿过来,其实就是一个原型链继承的语法糖。

    no-eval
    class SkinnedMesh extends THREE.Mesh {
      constructor(geometry, materials) {
        super(geometry, materials);
    
        this.idMatrix = SkinnedMesh.defaultMatrix();
        this.bones = [];
        this.boneMatrices = [];
        //...
      }
      update(camera) {
        //...
        super.update();
      }
      get boneCount() {
        return this.bones.length;
      }
      set matrixType(matrixType) {
        this.idMatrix = SkinnedMesh[matrixType]();
      }
      static defaultMatrix() {
        return new THREE.Matrix4();
      }
    }
    

    Lebab.io
    增强字面量对象

    var theProtoObj = {
      toString: function() {
        return "The ProtoOBject To string"
      }
    }
    
    var handler = () => "handler"
    
    
    var obj = {
        // __proto__
        __proto__: theProtoObj,
    
        //  ‘handler: handler’的简写
        handler,
    
        // 方法
        toString() {
    
         // Super calls
         return "d " + super.toString();
        },
    
        // 动态计算属性明
        [ "prop_" + (() => 42)() ]: 42
    };
    
    console.log(obj.handler)
    console.log(obj.handler())
    console.log(obj.toString())
    console.log(obj.prop_42)
    

    代码执行 需要chrome支持

    字符串模板

    var name = "Bob", time = "today";
    var multiLine = `This
    Line
    Spans Multiple
    Lines`
    
    console.log(`Hello ${name},how are you ${time}?`)
    console.log(multiLine)
    

    解构

    // list "matching"
    var [a, , b] = [1,2,3];
    console.log(a)
    console.log(b)
    

    对象也可以解构

    nodes = () => { return {op: "a", lhs: "b", rhs: "c"}}
    var { op: a, lhs: b , rhs: c } = nodes()
    console.log(a)
    console.log(b)
    console.log(c)
    

    箭头函数中的解构

    nodes = () => { return {lhs: "a", op: "b", rhs: "c"}}
    
    // binds `op`, `lhs` and `rhs` in scope
    var {op, lhs, rhs} = nodes()
    
    console.log(op)
    console.log(lhs)
    console.log(rhs)
    

    参数位置中的解构使用:

    function g({name: x}) {
      return x
    }
    
    function m({name}) {
      return name
    }
    
    console.log(g({name: 5}))
    console.log(m({name: 5}))
    

    未定义解构

    var [a] = []
    var [b = 1] = []
    var c = [];
    console.log(a)
    console.log(b);
    console.log(c);
    

    默认值

    function f(x, y=12) {
      return x + y;
    }
    
    console.log(f(3))
    

    展开运算符

    在函数中

    function f(x, y, z) {
      return x + y + z;
    }
    // Pass each elem of array as argument
    console.log(f(...[1,2,3]))
    

    在数组中

    var parts = ["shoulders", "knees"];
    var lyrics = ["head", ...parts, "and", "toes"]; 
    
    console.log(lyrics)
    

    展开运算符+字面量对象

    我们可以在创建对象做一些很酷炫的东西

    let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
    console.log(x); // 1
    console.log(y); // 2
    console.log(z); // { a: 3, b: 4 }
    
    // Spread properties
    let n = { x, y, ...z };
    console.log(n); // { x: 1, y: 2, a: 3, b: 4 }
    console.log(obj)
    

    悲剧的是现在还不支持

    npm install --save-dev babel-plugin-transform-object-rest-spread
    

    剩余参数(Rest)

    使用剩余参数操作我们可以无限制的添加参数

    function demo(part1, ...part2) {
        return {part1, part2}
    }
    
    console.log(demo(1,2,3,4,5,6))
    

    输出:demo(1,2,3,4,5,6) -> {"part1":1,"part2":[2,3,4,5,6]}

    Let

    代替var,比var更加健全的作用域。

    {
       var globalVar = "from demo1"
    }
    
    {
       let globalLet = "from demo2";
    }
    
    console.log(globalVar)
    console.log(globalLet)
    

    以后不会默认挂载在window变量下:

    et me = "go";  // globally scoped
    var i = "able"; // globally scoped
    
    console.log(window.me); 
    console.log(window.i);
    

    output:
    window.me -> undefined window.i -> able
    如果使用let不可以重复声明变量了

    let me = "foo";
    let me = "bar"; 
    console.log(me);
    

    output:
    SyntaxError: Identifier 'me' has already been declared

    var me = "foo";
    var me = "bar"; 
    console.log(me)
    

    output:
    me -> bar

    Const

    const是常量

    const a ="b"
    a="a"
    

    output:
    TypeError: Assignment to constant variable.
    这里需要注意的是const对象是可以变化的

    const a = {a:'a'}
    a.a = "b"
    console.log(a)
    

    output:
    a ->{"a":"b"}

    For..of

    迭代新类型,一个替代 for .. in 返回值将由keys替换values(for..in 遍历输入值为keys,而for..of是values)

    let list = [4, 5, 6];
    
    console.log(list)
    
    for (let i in list) {
       console.log(i);
    }
    

    output:

    list -> [4,5,6]
    i -> 0
    i -> 1
    i -> 2
    

    VS

    let list = [4, 5, 6];
    
    console.log(list)
    
    
    for (let i of list) {
       console.log(i); 
    }
    

    output:

    list -> [4,5,6]
    i -> 4
    i -> 5
    i -> 6
    

    Iterators(迭代器)

    这一种动态类型数组迭代器

    let infinite = {
      [Symbol.iterator]() {
        let c = 0;
        return {
          next() {
            c++;
            return { done: false, value: c }
          }
        }
      }
    }
    
    console.log("start");
    
    for (var n of infinite) {
      // truncate the sequence at 1000
      if (n > 10)
        break;
      console.log(n);
    }
    

    output:

    "start" -> start
    n -> 1
    n -> 2
    n -> 3
    n -> 4
    n -> 5
    n -> 6
    n -> 7
    n -> 8
    n -> 9
    n -> 10
    

    使用Typescript interfaces 我们看看他们的样子

    interface IteratorResult {
      done: boolean;
      value: any;
    }
    interface Iterator {
      next(): IteratorResult;
    }
    interface Iterable {
      [Symbol.iterator](): Iterator
    }
    

    Generators(生成器)

    生成器创建一个迭代器(iterators),比迭代器(iterators)更加动态,他不会跟踪记录状态,不支持done的概念

    var infinity = {
      [Symbol.iterator]: function*() {
        var c = 1;
        for (;;) {   
          yield c++;
        }
      }
    }
    
    console.log("start")
    for (var n of infinity) {
      // truncate the sequence at 1000
      if (n > 10)
        break;
      console.log(n);
    }
    

    output:

    "start" -> start
    n -> 1
    n -> 2
    n -> 3
    n -> 4
    n -> 5
    n -> 6
    n -> 7
    n -> 8
    n -> 9
    n -> 10
    

    使用TypeScript如下接口

    interface Generator extends Iterator {
        next(value?: any): IteratorResult;
        throw(exception: any);
    }
    

    function* Iterators and generator
    一个 yield*相关例子:

    function* anotherGenerator(i) {
      yield i + 1;
      yield i + 2;
      yield i + 3;
    }
    
    function* generator(i) {
      yield i;
      yield* anotherGenerator(i);
      yield i + 10;
    }
    
    var gen = generator(10);
    
    console.log(gen.next().value); 
    console.log(gen.next().value); 
    console.log(gen.next().value); 
    console.log(gen.next().value); 
    console.log(gen.next().value);
    

    output:

    gen.next().value -> 10
    gen.next().value -> 11
    gen.next().value -> 12
    gen.next().value -> 13
    gen.next().value -> 20
    

    Unicode

    ES6更好的支持Unicode

    var regex = new RegExp('\u{61}', 'u');
    
    console.log(regex.unicode)
    console.log("\uD842\uDFD7")
    console.log("\uD842\uDFD7".codePointAt())
    

    output:

    regex.unicode -> true
    "𠯗" -> 𠯗
    "𠯗".codePointAt() -> 134103
    

    模块和模块加载器

    原生模块支持

    import defaultMember from "module-name";
    import * as name from "module-name";
    import { member } from "module-name";
    import { member as alias } from "module-name";
    import { member1 , member2 } from "module-name";
    import { member1 , member2 as alias2 , [...] } from "module-name";
    import defaultMember, { member [ , [...] ] } from "module-name";
    import defaultMember, * as name from "module-name";
    import "module-name";
    export { name1, name2, …, nameN };
    export { variable1 as name1, variable2 as name2, …, nameN };
    export let name1, name2, …, nameN; // also var
    export let name1 = …, name2 = …, …, nameN; // also var, const
    
    export expression;
    export default expression;
    export default function (…) { … } // also class, function*
    export default function name1(…) { … } // also class, function*
    export { name1 as default, … };
    
    export * from …;
    export { name1, name2, …, nameN } from …;
    export { import1 as name1, import2 as name2, …, nameN } from …;
    

    Import Export

    Set

    Sets作为一个数学的配对物,所有的子项都是唯一的,就类似SQL中的distinct

    var set = new Set();
    set.add("Potato").add("Tomato").add("Tomato");
    console.log(set.size)
    console.log(set.has("Tomato"))
    
    for(var item of set) {
       console.log(item)
    }
    
    set.size -> 2
    set.has("Tomato") -> true
    item -> Potato
    item -> Tomato
    

    Set

    WeakSet

    WeakSet能让你存储对象到集合中,对象如果没有引用将会被回收。(只能存储对象,而不能是其他类型,不能被遍历,因为成员是弱引用,随时有可能消失)

    var item = { a:"Potato"}
    var set = new WeakSet();
    set.add({ a:"Potato"}).add(item).add({ a:"Tomato"}).add({ a:"Tomato"});
    console.log(set.size)
    console.log(set.has({a:"Tomato"}))
    console.log(set.has(item))
    
    for(let item of set) {
       console.log(item)
    }
    

    output

    set.size -> undefined
    set.has({a:"Tomato"}) -> false
    set.has(item) -> true
    TypeError: undefined is not a function
    

    WeakSet

    Map

    Maps,顾名思义数据字典

    var map = new Map();
    map.set("Potato", 12);
    map.set("Tomato", 34);
    
    console.log(map.get("Potato"))
    
    
    for(let item of map) {
       console.log(item)
    }
    
    
    for(let item in map) {
       console.log(item)
    }
    

    output

    map.get("Potato") -> 12
    item -> ["Potato",12]
    item -> ["Tomato",34]
    
    

    key值可以使用对象,但是非同一引用不能获取值

    var map = new Map();
    var key = {a: "a"}
    map.set(key, 12);
    
    
    console.log(map.get(key))
    console.log(map.get({a: "a"}))
    

    output:

    map.get(key) -> 12
    map.get({a: "a"}) -> undefined
    

    weakMap

    所有key值都为对象,且key值对象只能保持弱引用。

    var wm = new WeakMap();
    
    var o1  = {}
    var o2  = {}
    var o3  = {}
    
    
    wm.set(o1, 1);
    wm.set(o2, 2);
    wm.set(o3, {a: "a"});
    wm.set({}, 4);
    
    console.log(wm.get(o2));
    console.log(wm.has({}))
    
    delete o2;
    
    console.log(wm.get(o3));
    
    for(let item in wm) {
       console.log(item)
    }
    

    weakMap

    Proxies

    代理可以用来改变对象的行为,它允许我们定义一个trap。

    var obj = function ProfanityGenerator() {
        return {
           words: "Horrible words"    
        }
    }()
    
    var handler = function CensoringHandler() {
            return {
            get: function (target, key) {
                return target[key].replace("Horrible", "Nice");
            },
        }
    
    }()
    
    var proxy = new Proxy(obj, handler);
    
    console.log(proxy.words);
    

    The following traps are available:

    no-eval
    var handler =
    {
      get:...,
      set:...,
      has:...,
      deleteProperty:...,
      apply:...,
      construct:...,
      getOwnPropertyDescriptor:...,
      defineProperty:...,
      getPrototypeOf:...,
      setPrototypeOf:...,
      enumerate:...,
      ownKeys:...,
      preventExtensions:...,
      isExtensible:...
    }
    

    Proxies

    Symbols

    Symbols是一个新的类型.用于创建一个匿名属性

    var typeSymbol = Symbol("type");
    
    class Pet {
    
      constructor(type) {
    
        this[typeSymbol] = type;
    
      }
      getType() {
         return this[typeSymbol];
      }
    
    }
    
    
    var a = new Pet("dog");
    console.log(a.getType());
    console.log(Object.getOwnPropertyNames(a))
    
    
    console.log(Symbol("a") === Symbol("a"))
    

    More info

    Inheritable Built-ins(内置对象可以继承)

    现在我们可以继承原生的class

    class CustomArray extends Array {
    
    }
    
    var a = new CustomArray();
    
    a[0] = 2
    console.log(a[0])
    

    如果没有使用Proxies的Aarry使用继承是不可能改变原生getter

    New Library(新库)

    各种新的方法和常量

    console.log(Number.EPSILON)
    console.log(Number.isInteger(Infinity))
    console.log(Number.isNaN("NaN"))
    
    console.log(Math.acosh(3))
    console.log(Math.hypot(3, 4))
    console.log(Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2))
    
    console.log("abcde".includes("cd") )
    console.log("abc".repeat(3) )
    
    
    console.log(Array.of(1, 2, 3) )
    console.log([0, 0, 0].fill(7, 1) )
    console.log([1, 2, 3].find(x => x == 3) )
    console.log([1, 2, 3].findIndex(x => x == 2)) 
    console.log([1, 2, 3, 4, 5].copyWithin(3, 0)) 
    console.log(["a", "b", "c"].entries() )
    console.log(["a", "b", "c"].keys() )
    console.log(["a", "b", "c"].values() )
    
    console.log(Object.assign({}, { origin: new Point(0,0) }))
    

    Documentation: Number, Math, Array.from, Array.of, Array.prototype.copyWithin, Object.assign

    二进制和八进制

    字面二进制和八进制数字

    console.log(0b11111)
    console.log(0o2342)
    
    console.log(0xff); // also in es5
    

    Promises

    Need a quick always resolved promise?

    var p1 = new Promise((resolve, reject) => {
      setTimeout(() => resolve("1"), 101)
    })
    var p2 = new Promise((resolve, reject) => {
      setTimeout(() => resolve("2"), 100)
    })
    
    Promise.race([p1, p2]).then((res) => {
       console.log(res)
    })
    
    Promise.all([p1, p2]).then((res) => {
       console.log(res)
    })
    

    Quick Promise

    Need a quick always resolved promise?

    var p1 = Promise.resolve("1")
    var p2 = Promise.reject("2")
    
    Promise.race([p1, p2]).then((res) => {
       console.log(res)
    })
    

    Fail fast

    If a promise fails, all and race will reject as well.

    var p1 = new Promise((resolve, reject) => {
      setTimeout(() => resolve("1"), 1001)
    })
    var p2 = new Promise((resolve, reject) => {
      setTimeout(() => reject("2"), 1)
    })
    
    Promise.race([p1, p2]).then((res) => {
       console.log("success" + res)
    }, res => {
       console.log("error " + res)
    })
    
    Promise.all([p1, p2]).then((res) => {
       console.log("success" + res)
    }, res => {
       console.log("error " + res)
    })
    

    More Info

    Reflect

    New type of meta programming with new API for existing and also a few new methods.

    var z = {w: "Super Hello"}
    var y = {x: "hello", __proto__: z};
    
    console.log(Reflect.getOwnPropertyDescriptor(y, "x"));
    console.log(Reflect.has(y, "w"));
    console.log(Reflect.ownKeys(y, "w"));
    
    console.log(Reflect.has(y, "x"));
    console.log(Reflect.deleteProperty(y,"x"))
    console.log(Reflect.has(y, "x"));
    

    More Info

    Tail Call Optimization

    ES6 should fix ensure tail calls do not generate stack overflow. (Not all implementations work).

    function factorial(n, acc = 1) {
        if (n <= 1) return acc; 
        return factorial(n - 1, n * acc);
    }
    console.log(factorial(10))
    console.log(factorial(100))
    console.log(factorial(1000))
    console.log(factorial(10000))
    console.log(factorial(100000))
    console.log(factorial(1000000))
    

    相关文章

      网友评论

        本文标题:ES6特性

        本文链接:https://www.haomeiwen.com/subject/iixlottx.html