美文网首页
[译] You Might Not Use ES6

[译] You Might Not Use ES6

作者: 雨蒙_snow | 来源:发表于2019-01-15 09:45 被阅读0次

    箭头函数

    与函数表达式相比,箭头函数表达式(也称为胖箭头函数)的语法更简介,并且不会创建自己的 this
    箭头函数相当于匿名函数。

    ES6:

    [1, 2, 3].map(n => n * 2);
    // -> [ 2, 4, 6 ]
    
    

    ES5 实现:

    [1, 2, 3].map(function(n) { return n * 2; }, this);
    // -> [ 2, 4, 6 ]
    
    

    ES6:

    var evens = [2, 4, 6, 8, 10];
    
    // 表达式正文
    var odds = evens.map(v => v + 1);
    var nums = evens.map((v, i) => v + i);
    
    console.log(odds);
    // -> [3, 5, 7, 9, 11]
    
    console.log(nums);
    // -> [2, 5, 8, 11, 14]
    
    // 声明式正文
    var fives = [];
    nums = [1, 2, 5, 15, 25, 32];
    nums.forEach(v => {
      if (v % 5 === 0)
        fives.push(v);
    });
    
    console.log(fives);
    // -> [5, 15, 25]
    
    // 作用域中的 this
    var bob = {
      _name: 'Bob',
      _friends: [],
      printFriends() {
        this._friends.forEach(f =>
          console.log(this._name + ' knows ' + f));
      }
    }
    
    

    ES5:

    'use strict';
    
    var evens = [2, 4, 6, 8, 10];
    
    // 表达式正文
    var odds = evens.map(function (v) {
      return v + 1;
    }, this);
    var nums = evens.map(function (v, i) {
      return v + i;
    }, this);
    
    console.log(odds);
    // -> [3, 5, 7, 9, 11]
    
    console.log(nums);
    // -> [2, 5, 8, 11, 14]
    
    var fives = [];
    nums = [1, 2, 5, 15, 25, 32];
    
    // 声明式正文
    nums.forEach(function (v) {
      if (v % 5 === 0) {
        fives.push(v);
      }
    }, this);
    
    console.log(fives);
    // -> [5, 15, 25]
    
    // Lexical this
    var bob = {
      _name: 'Bob',
      _friends: [],
      printFriends: function printFriends() {
        this._friends.forEach(function (f) {
          return console.log(this._name + ' knows ' + f);
        }, this);
      }
    };
    
    

    块级作用域函数

    块作用域绑定提供了函数和顶级作用域以外的作用域。
    这确保你的变量不会超出他们定义的范围内。

    ES6:

    // let 声明一个局部块作用域,在 ES6 中可以任意的初始化一个值
    
    'use strict';
    
    var a = 5;
    var b = 10;
    
    if (a === 5) {
      let a = 4; // 作用域在 if 块中
      var b = 1; // 作用域在函数内部
    
      console.log(a);  // 4
      console.log(b);  // 1
    }
    
    console.log(a); // 5
    console.log(b); // 1
    
    

    ES5:

    'use strict';
    
    var a = 5;
    var b = 10;
    
    if (a === 5) {
      // 在实现上更像下面这样
      (function () {
        var a = 4;
        b = 1;
    
        console.log(a); // 4
        console.log(b); // 1
      })();
    }
    
    console.log(a); // 5
    console.log(b); // 1
    
    

    ES6:

    // const 在 ES6 中创建只读的属性常量
    'use strict';
    // 将 favorite 定义为常量并且赋值为 7
    const favorite = 7;
    // 试图覆盖常量
    try {
      favorite = 15;
    } catch (err) {
      console.log('my favorite number is still: ' + favorite);
      // 仍然会输出 7
    }
    
    

    ES5:

    'use strict';
    // 将 favorite 定义为一个不可写的“常量”,并将其赋值为 7。
    Object.defineProperties(window, {
      favorite: {
        value: 7,
        enumerable: true
      }
    });
    // 属性描述默认为 false,并且 const 是可枚举的
    var favorite = 7;
    // 试图覆盖常量
    favorite = 15;
    // 仍然会输出 7
    console.log('my favorite number is still: ' + favorite);
    
    

    模版字符串

    ES6 模版字符串是可以包含嵌入表达式的字符串,有时也被叫做插值表达式

    ES6:

    // 表达式占位符的基本用法
    var person = 'Addy Osmani';
    console.log(`Yo! My name is ${person}!`);
    
    // 表达式也可以用在对象中
    var user = {name: 'Caitlin Potter'};
    console.log(`Thanks for getting this into V8, ${user.name}.`);
    
    // 插值表达式:作用之一可以用来计算
    var a = 50;
    var b = 100;
    console.log(`The number of JS frameworks is ${a + b} and not ${2 * a + b}.`);
    
    // 多行字符串不需要换行符
    console.log(`string text line 1
    string text line 2`);
    
    // 函数内部表达式
    function fn() { return 'result'; }
    console.log(`foo ${fn()} bar`);
    
    

    ES5:

    'use strict';
    
    // 表达式占位符的基本用法
    var person = 'Addy Osmani';
    console.log('Yo! My name is ' + person + '!');
    
    // 表达式也可以用在对象中
    var user = { name: 'Caitlin Potter' };
    console.log('Thanks for getting this into V8, ' + user.name + '.');
    
    // 插值表达式:作用之一可以用来计算
    var a = 50;
    var b = 100;
    console.log('The number of JS frameworks is ' + (a + b) + ' and not ' + (2 * a + b) + '.');
    
    // 多行字符串
    console.log('string text line 1\nstring text line 2');
    // 或者下面这种写法
    console.log('string text line 1\n\
    string text line 2');
    
    // 函数内部表达式
    function fn() {
      return 'result';
    }
    console.log('foo ' + fn() + ' bar');
    
    

    计算属性

    计算属性名允许你基于表达式在对象文本中指定属性

    ES6:

    var prefix = 'foo';
    var myObject = {
      [prefix + 'bar']: 'hello',
      [prefix + 'baz']: 'world'
    };
    
    console.log(myObject['foobar']);
    // -> hello
    console.log(myObject['foobaz']);
    // -> world
    
    

    ES5:

    'use strict';
    
    var prefix = 'foo';
    var myObject = {};
    
    myObject[prefix + 'bar'] = 'hello';
    myObject[prefix + 'baz'] = 'world';
    
    console.log(myObject['foobar']);
    // -> hello
    console.log(myObject['foobaz']);
    // -> world
    
    

    解构赋值

    解构赋值语法是一个JavaScript表达式,它可以使用数组映射和对象文本构造的语法从数组和对象中提取值,对变量进行赋值。

    ES6:

    var {foo, bar} = {foo: 'lorem', bar: 'ipsum'};
    // foo => lorem and bar => ipsum
    
    

    ES5:

    'use strict';
    
    var _ref = { foo: 'lorem', bar: 'ipsum' };
    
    // foo => lorem and bar => ipsum
    var foo = _ref.foo;
    var bar = _ref.bar;
    
    

    ES3:

    with({foo: 'lorem', bar: 'ipsum'}) {
      // foo => lorem and bar => ipsum
    }
    
    

    ES6:

    var [a, , b] = [1,2,3];
    
    

    ES6 (shimming using Symbol.iterator):

    'use strict';
    
    var _slicedToArray = function (arr, i) {
      if (Array.isArray(arr)) {
        return arr;
      } else {
        var _arr = [];
    
        for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
          _arr.push(_step.value);
    
          if (i && _arr.length === i) {
            break;
          }
        }
    
        return _arr;
      }
    };
    
    var _ref = [1, 2, 3];
    
    var _ref2 = _slicedToArray(_ref, 3);
    
    var a = _ref2[0];
    var b = _ref2[2];
    
    

    ES5:

    String.prototype.asNamedList = function () {
      return this.split(/\s*,\s*/).map(function (name, i) {
        return name ? ('var ' + name + '=slice(' + i + ', ' + (i + 1) + ')[0]') : '';
      }).join(';');
    };
    
    with([1,2,3]) {
      eval('a, , b'.asNamedList());
    }
    
    

    默认参数

    默认参数允许函数具有可选参数,而不需要检查参数的长度或是否未定义。

    ES6:

    function greet(msg='hello', name='world') {
      console.log(msg,name);
    }
    
    greet();
    // -> hello world
    greet('hey');
    // -> hey world
    
    

    ES5:

    'use strict';
    
    function greet() {
      // 如果像这样访问 arguments[0],则可以简单地进行访问 msg 变量名
      var msg = arguments[0] === undefined ? 'hello' : arguments[0];
      var name = arguments[1] === undefined ? 'world' : arguments[1];
      console.log(msg, name);
    }
    
    function greet(msg, name) {
      (msg === undefined) && (msg = 'hello');
      (name === undefined) && (name = 'world');
      console.log(msg,name);
    }
    
    // 对未定义的参数进行检查的基本方法
    function greet(msg, name) {
      console.log(
        defaults(msg, 'hello'),
        defaults(name, 'world')
      );
    }
    
    greet();
    // -> hello world
    greet('hey');
    // -> hey world
    
    

    ES6:

    function f(x, y=12) {
      // y 的指是 12 如果没有接收(或者接收的是 undefined )
      return x + y;
    }
    
    f(3) === 15;
    
    

    ES5:

    'use strict';
    
    function f(x, y) {
      if (y === undefined) {
        y = 12;
      }
    
      return x + y;
    }
    
    f(3) === 15;
    
    

    Iterators 和 For-Of 循环

    遍历器是可以遍历容器的对象。这是一种使类工作在for..of循环的有用方法。
    接口类似于遍历器接口。
    迭代一个for..of循环的形式如下。

    ES6:

    // 当前环境,将从数组中获取一个遍历器,并对其进行循环,从中获取值
    for (let element of [1, 2, 3]) {
      console.log(element);
    }
    // => 1 2 3
    
    

    ES6 (without using for-of, if Symbol is supported):

    'use strict';
    
    for (var _iterator = [1, 2, 3][Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
      var element = _step.value;
      console.log(element);
    }
    
    // => 1 2 3
    
    

    ES5 (approximates):

    // 使用 forEach()
    // 不需要在包含的范围中声明索引和元素变量。它们被作为参数提供给遍历器,并被限定在遍历的范围内。
    var a = [1,2,3];
    a.forEach(function (element) {
        console.log(element);
    });
    
    // => 1 2 3
    
    // 使用  for 循环
    var a = [1,2,3];
    for (var i = 0; i < a.length; ++i) {
        console.log(a[i]);
    }
    // => 1 2 3
    
    

    注意Symbol的使用。ES5 需要一个正确的Symbol polyfill才能正常使用。

    Class

    class 实现了 ES6 规范草案中描述的类语法和语义。
    class 是复用代码最好的方法。
    一些 JS 库提供了类和继承,但它们并不相互兼容。

    ES6:

    class Hello {
      constructor(name) {
        this.name = name;
      }
    
      hello() {
        return 'Hello ' + this.name + '!';
      }
    
      static sayHelloAll() {
        return 'Hello everyone!';
      }
    }
    
    class HelloWorld extends Hello {
      constructor() {
        super('World');
      }
    
      echo() {
        alert(super.hello());
      }
    }
    
    var hw = new HelloWorld();
    hw.echo();
    
    alert(Hello.sayHelloAll());
    
    

    ES5 ( 类似功能 ):

    function Hello(name) {
      this.name = name;
    }
    
    Hello.prototype.hello = function hello() {
      return 'Hello ' + this.name + '!';
    };
    
    Hello.sayHelloAll = function () {
      return 'Hello everyone!';
    };
    
    function HelloWorld() {
      Hello.call(this, 'World');
    }
    
    HelloWorld.prototype = Object.create(Hello.prototype);
    HelloWorld.prototype.constructor = HelloWorld;
    HelloWorld.sayHelloAll = Hello.sayHelloAll;
    
    HelloWorld.prototype.echo = function echo() {
      alert(Hello.prototype.hello.call(this));
    };
    
    var hw = new HelloWorld();
    hw.echo();
    
    alert(Hello.sayHelloAll());
    
    

    更详细的介绍可以查看 Babel

    Modules

    模块功能大部分是实现了,一些加载api仍然在改进中。
    模块试图解决依赖关系和部署中的许多问题,允许用户使用显式导出创建模块,从这些模块中导入特定的导出名称,并保持这些名称的独立性。

    app.js - ES6

    import math from 'lib/math';
    console.log('2π = ' + math.sum(math.pi, math.pi));
    
    

    app.js - ES5

    var math = require('lib/math');
    console.log('2π = ' + math.sum(math.pi, math.pi));
    
    

    lib/math.js - ES6

    export function sum(x, y) {
      return x + y;
    }
    export var pi = 3.141593;
    
    

    lib/math.js - ES5

    exports.sum = sum;
    function sum(x, y) {
      return x + y;
    }
    var pi = exports.pi = 3.141593;
    
    

    lib/mathplusplus.js - ES6

    export * from 'lib/math';
    export var e = 2.71828182846;
    export default function(x) {
      return Math.exp(x);
    }
    
    

    lib/mathplusplus.js - ES5

    var Math = require('lib/math');
    
    var _extends = function (target) {
      for (var i = 1; i < arguments.length; i++) {
        var source = arguments[i];
        for (var key in source) {
          target[key] = source[key];
        }
      }
    
      return target;
    };
    
    var e = exports.e = 2.71828182846;
    exports['default'] = function (x) {
      return Math.exp(x);
    };
    
    module.exports = _extends(exports['default'], exports);
    
    

    数字字面量

    ES6:

    var binary = [
      0b0,
      0b1,
      0b11
    ];
    console.assert(binary === [0, 1, 3]);
    
    var octal = [
      0o0,
      0o1,
      0o10,
      0o77
    ];
    console.assert(octal === [0, 1, 8, 63]);
    
    

    ES5:

    'use strict';
    
    var binary = [0, 1, 3];
    console.assert(binary === [0, 1, 3]);
    
    var octal = [0, 1, 8, 63];
    console.assert(octal === [0, 1, 8, 63]);
    
    

    属性赋值方法

    对象中支持方法语法, 比如说 toString()

    ES6:

    var object = {
      value: 42,
      toString() {
        return this.value;
      }
    };
    
    console.log(object.toString() === 42);
    // -> true
    
    

    ES5:

    'use strict';
    
    var object = {
      value: 42,
      toString: function toString() {
        return this.value;
      }
    };
    
    console.log(object.toString() === 42);
    // -> true
    
    

    对象属性的简介表示

    在对象中的属性名和属性值相同时可以忽略属性值。

    ES6:

    function getPoint() {
      var x = 1;
      var y = 10;
    
      return {x, y};
    }
    
    console.log(getPoint() === {
      x: 1,
      y: 10
    });
    
    

    ES5:

    'use strict';
    
    function getPoint() {
      var x = 1;
      var y = 10;
    
      return { x: x, y: y };
    }
    
    console.log(getPoint() === {
      x: 1,
      y: 10
    });
    
    

    Rest 参数

    rest 参数允许函数在不使用 arguments 对象的情况下具有可变数量的参数。
    rest 参数是数组的一个实例,因此所有的数组方法都可以使用。

    ES6:

    function f(x, ...y) {
      // y 是个数组
      return x * y.length;
    }
    
    console.log(f(3, 'hello', true) === 6);
    // -> true
    
    

    ES5:

    'use strict';
    
    function f(x) {
      var y = [];
      y.push.apply(y, arguments) && y.shift();
    
      // y 是个数组
      return x * y.length;
    }
    
    console.log(f(3, 'hello', true) === 6);
    // -> true
    
    

    扩展运算符

    扩展运算符是和 rest 参数相反的。
    它允许将数组展开为多个形式的参数。

    ES6:

    function add(a, b) {
      return a + b;
    }
    
    let nums = [5, 4];
    
    console.log(add(...nums));
    
    

    ES5:

    'use strict';
    
    var _toArray = function (arr) {
      return Array.isArray(arr) ? arr : [].slice.call(arr);
    };
    
    function add(a, b) {
      return a + b;
    }
    
    var nums = [5, 4];
    console.log(add.apply(null, _toArray(nums)));
    
    

    ES6:

    function f(x, y, z) {
      return x + y + z;
    }
    // 传递数组的每一个参数
    f(...[1,2,3]) === 6;
    
    

    ES5:

    'use strict';
    
    function f(x, y, z) {
      return x + y + z;
    }
    // 传递数组的每一个参数
    f.apply(null, [1, 2, 3]) === 6;
    
    

    Proxy

    ES6:

    var target = function () {
      return 'I am the target';
    };
    
    var handler = {
      apply: function (receiver, ...args) {
        return 'I am the proxy';
      }
    };
    
    var p = new Proxy(target, handler);
    console.log(p() === 'I am the proxy');
    // -> true
    
    

    ES5:

    在 ES5 中没有 proxy, 没有类似的方法去拦截。

    类数组

    Array.from 使有着单一的参数类数组或者列表(像:arguments, NodeList, DOMTokenList(当做classList),NamedNodeMap(属性使用))返回一个新的数组实例。

    ES6:

    var listFriends = function() {
      var friends = Array.from(arguments);
      friends.forEach(friend => {
        console.log(friend);
      });
    };
    listFriends('ann', 'bob');
    // -> 'ann'
    // -> 'bob'
    
    var divs = document.querySelectorAll('div');
    Array.from(divs).forEach(node => {
        console.log(node);
    });
    // -> <div>...</div>
    // -> <div>...</div>
    
    

    ES5:

    var listFriends = function() {
      var friends = [].slice.call(arguments)
      friends.forEach(function(friend) {
        console.log(friend);
      });
    };
    listFriends('ann', 'bob');
    // -> 'ann'
    // -> 'bob'
    
    var divsArray = [].slice.call(document.querySelectorAll('div'));
    divsArray.forEach(function(node) {
        console.log(node);
    });
    // -> <div>...</div>
    // -> <div>...</div>
    
    

    参考

    重点

    如果有错误或者错别字,还请给我留言指出,谢谢。

    我们下期见。

    相关文章

      网友评论

          本文标题:[译] You Might Not Use ES6

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