ECMAScript6新特性


参考资料

ES6新增的编程风格

  • let 块级作用域和const 全局常量
    • var命令存在变量提升效用,let命令没有这个问题
    • const 考虑到全局环境、变量值不变和线程安全
  • 字符串
    • 静态字符串一律用单引号
    • 动态字符串用反引号
    • 字符串遍历接口for ... of
    • includes()startsWith()endsWith()确定一个字符串是否包含在另一个字符串中
    • repeat():返回一个新字符串,将原字符串重复整数n次(n为正数,小数会取整)
      const a = "foobar";
      const b = `foo${a}bar`;//"foofoobarbar"
      let text = String.fromCodePoint(0x20BB7);
      for (let i = 0; i < text.length; i++) {
      console.log(text[i]);//" " " " 不是期望的结果,将中文识别成两个字符
      }
      for(let i of text) {
      console.log(i); //"𠮷"
      }
      'x'.repeat(3);//'xxx'
      'na'.repeat(0);//''
      
  • 解析构值
    • 使用数组成员对变量赋值时,优先使用解构赋值const [first, second] = arr;
    • 函数的参数如果是对象的成员,优先使用解构赋值
      function getFullName({first, second}) {}
      function processInput(input) {
      return {left, right, top, bottom};
      }
      const {left, right} = processInput(input);
      //交换变量的值
      [x, y] = [y, x];
      
  • 数组
    • 使用扩展运算符(…)拷贝数组const itemCopy = [...items];
    • 使用Array.from方法,将类似数组的对象转化为数组
      const foo = document.querySelectorAll('.foo');
      const nodes = Array.from(foo);
      
  • 函数
    • 立即执行函数可以写成箭头函数的形式
      (() => {
      console.log('hello from Javascript');
      })();
      [1, 2, 3].map(x => x * x);
      
      • 箭头函数取代Function.prototype.bind
    • 不要在函数体内使用arguments变量,使用rest运算符代替,因为rest运算符显式表明你想要获得参数,而且arguments是一个类似数组的对象,而rest运算符可以提供一个真正的数组。
      //bad
      function concatenateAll(){
      const args = Array.prototype.slice.call(arguments);
      return args.join('');
      }
      //good
      function concatenateAll(...args) {
      return args.join('');
      }
      
      • Array.prototype.slice.call(arguments)
        • 能将具有length属性的对象(key值为数字)转成数组
        • 没有length属性返回空数组
  • Map结构
    只有模拟现实世界的实体对象,才使用Object。如果只是key:value的数据结构,使用Map结构。因为Map有内建的遍历机制。
    let map = new Map(arr);
    map.set('first', 'hello');
    for(let key of map.keys()) {// let [key] of map
    console.log(key);
    }
    for(let value of map.values()){//let [, value] of map
    console.log(value);
    }
    for(let item of map.entries()){
    console.log(items[0], );
    }
    for(let [key, value] of map) {
    console.log(key + 'is' + value);
    }
    
  • Set结构
    Set本身是一个构造函数,成员值是唯一的。接受一个数组或者具有iterable接口的其他数据结构作为参数,用来初始化。两个对象总是不相等。
  • add(value):返回Set结构本身
  • delete(value):返回布尔值,表明删除是否成功
  • has(value):返回布尔值,是否为Set成员
  • clear():清除所有成员,无返回值

    const s = new Set();
    [2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
    for(let i of s) {
    console.log(i);//2 3 5 4
    }
    //数组去重
    [...new Set(array)]
    
  • Class 取代prototype,类似Java语法

    class Queue {
    constructor(contents = []) {
      this._queue = [...contents];
    }
    pop() {
      const value = this.queue[0];
      this._queue.splice(0, 1);
      return value;
    }
    }
    class PeekableQueue extends Queue {
    peek() {
      return this._queue[0];
    }
    }
    
  • 模块
    //Javascript标准语法
    const React = require('react');
    var Breadcrumbs = React.createClass({
    render() {
      return 
  • ESLint
    ESLint是一个语法规则和代码风格的检查工具

  • 模板字符串:模板字符串中嵌入变量,需要将变量名写在${}之中,多行字符串保留空格和缩进

    $('#result').append(`
    There are  ${basket.count}  items in your basket,  ${basket.onSale} are on sale!
    `);
    
  • Number.EPSILOW:相当于2的-52次方,是JavaScript能够表示的最小精度,误差如果小于这个值,就可以认为已经没有意义了,即不存在误差。
    0.1+0.2
    // 0.30000000000000004
    0.1 + 0.2 - 0.3
    // 5.551115123125783e-17
    0.1 + 0.2 == 0.3
    //false
    function withErrorMargin(left, right) {
    return Math.abs(left - right) < Number.EPSILOW * Math.pow(2, 2);//误差设为2的-50次方
    }
    
  • 函数默认参数值
    • 允许为函数参数设置默认值
    • 参数默认值不是传值的,而是每次计算表达式的值
    • 定义默认值的参数应该是函数的尾参数,否则没法省略
  • 箭头函数

    • 函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象
    • 不可以当作构造函数,也就是说不可以使用new命令,否则会抛出一个错误
    • 不可以使用arguments对象,该对象在函数体内不存在,可以用rest参数替代
    • 不可以用yield命令
  • 尾调用: 某个函数的最后一步是调用另一个函数

    function f() {
    let m = 1;
    let n = 2;
    return g(m + n); //调用后还有其他操作,或者不返回都不是尾调用
    }
    
    • 函数调用会在内存形成一个调用帧,所有调用帧会形成一个调用栈
    • 如果函数g不是尾调用,函数f就需要保存内部变量m和n的值、g的调用位置等信息。但由于调用g之后,函数f就结束了,所以执行到最后一步,完全可以删除f(x)的调用帧,只保留g(3)的调用帧。
    • 尾调用优化(Tail call optimization),即只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是“尾调用优化”的意义。
    • 只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”。
  • 尾递归:函数调用自身,称为递归。如果尾调用自身,就称为尾递归。

    • 递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。
      //非尾递归:需要保存n个调用记录,复杂度O(n)
      function factorial(n) {
      if(n == 1) return 1;
      return n * factorial(n - 1);
      }
      //尾递归,只保留一个调用记录,复杂度O(1)
      function factorial(n, total = 1) {
      if(n == 1) return total;
      return factorial(n - 1, n * total);
      }
      
  • 蹦床函数(trampoline):将递归执行转为循环执行
    //蹦床函数
    function trampoline(f) {
    while (f && f instanceof Function) {
      f = f();
    }
    return f;
    }
    //栈溢出
    function sum(x, y) {
    if(y > 0) {
      return sum(x + 1, y - 1);
    } else {
      return x;
    }
    }
    sum(1, 1000000);
    //改写返回另一个函数
    function sum(x, y) {
    if(y > 0) {
      return sum.bind(null, x + 1, y - 1);
    } else {
      return x;
    }
    }
    trampoline(sum(1, 100000))
    
  • 数组深度复制
    // ES5
    const a1 = [1, 2];
    const a2 = a1.concat();
    //ES6
    const a2 = [...a1];
    //或者
    const [...a2] = a1;
    
  • 数组合并
    // ES5
    arr1.concat(arr2, arr3);//浅拷贝
    //ES6
    [..arr1, ...arr2, ...arr3];//浅拷贝
    //字符串转数组
    [...'hello']//["h","e","l","l","o"]
    
  • Object.assign:方法用于对象的合并,将源对象的所有可枚举属性,复制到目标对象,方法的第一个参数是目标对象,后面的参数都是源对象。
    const target = { a: 1 };
    const source1 = { b: 2 };
    const source2 = { c: 3 };
    Object.assign(target, source1, source2); //浅拷贝,源对象值改变,会引起变化
    target // {a:1, b:2, c:3}
    //为对象添加属性
    class Point {
    constructor(x, y) {
      Object.assign(this, {x, y});
    }
    }
    //为对象添加方法
    Object.assign(SomeClass.prototype, {
    someMethod(arg1, arg2) {
      ···
    },
    anotherMethod() {
      ···
    }
    });
    

    Promise



文章作者: Susie Chang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Susie Chang !
 上一篇
事件详解 事件详解
事件流 事件流描述的是从页面中接收事件的顺序 IE的事件流叫做事件冒泡,即时间开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档) 事件捕获 的思想是不太具体的节点应该更早的接收到事件,而最具
2018-10-10
下一篇 
Express基础及源码解析 Express基础及源码解析
express是什么Express是基于Node.js平台的Web开发框架,是一个路由和中间件 Web 框架,其自身只具有最低程度的功能:Express 应用程序基本上是一系列中间件函数调用。核心特性: 设置中间件来响应HTTP请求 定义
2018-09-27
  目录