zoukankan      html  css  js  c++  java
  • ES6的一些常用特性

    Default Parameters(默认参数)

    还记得我们以前不得不通过下面方式来定义默认参数:

    复制代码
    var link = function (height, color, url) {
        var height = height || 50;
        var color = color || 'red';
        var url = url || 'http://azat.co';
        ...
    }
    复制代码

    但在ES6,我们可以直接把默认值放在函数申明里:

    var link = function(height = 50, color = 'red', url = 'http://azat.co') {
      ...
    }

    Multi-line Strings (多行字符串)

    ES6的多行字符串是一个非常实用的功能。在ES5中,我们不得不使用以下方法来表示多行字符串:

    复制代码
    var roadPoem = 'Then took the other, as just as fair,nt'
        + 'And having perhaps the better claimnt'
        + 'Because it was grassy and wanted wear,nt'
        + 'Though as for that the passing therent'
        + 'Had worn them really about the same,nt';
    var fourAgreements = 'You have the right to be you.n
        You can only be you when you do your best.';
    复制代码

    然而在ES6中,仅仅用反引号就可以解决了:

    复制代码
    var roadPoem = `Then took the other, as just as fair,
        And having perhaps the better claim
        Because it was grassy and wanted wear,
        Though as for that the passing there
        Had worn them really about the same,`;
    var fourAgreements = `You have the right to be you.
        You can only be you when you do your best.`;
    复制代码

    Template Literals(模板对象)

    在其它语言中,使用模板和插入值是在字符串里面输出变量的一种方式。因此,在ES5,我们可以这样组合一个字符串:

    var name = 'Your name is ' + first + ' ' + last + '.';
    var url = 'http://localhost:3000/api/messages/' + id;

    幸运的是,在ES6中,我们可以使用新的语法$ {NAME},并把它放在反引号里

    var name = `Your name is ${first} ${last}. `;
    var url = `http://localhost:3000/api/messages/${id}`;

    块级作用域

    ES6提出了两个新的声明变量的命令:letconst。其中,let完全可以取代var,因为两者语义相同,而且let没有副作用。

    (1).使用let 取代 var

    1.for循环的计数器,就很合适使用let命令。

    复制代码
    /*  let */
    for (let i = 0; i < 10; i++) {}
    console.log(i);   //ReferenceError: i is not defined
    
    /* var */
    for (var i = 0; i < 10; i++) {}
    console.log(i);   // 10
    复制代码

    2.var命令存在变量提升效用,let命令没有这个问题。

    复制代码
    /* let */
    if(true) {
      console.log(x); // ReferenceError
      let x = 'hello';
    }
    
    /* var */
    if(true) {
      console.log(x); // hello
      var x = 'hello';
    }
    
    //使用var,有输出,这违反了变量先声明后使用的原则。所以,建议不再使用var命令,而是使用let命令取代。
    复制代码

    (2)全局常量和线程安全

    letconst之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。

    const优于let有几个原因。一个是const可以提醒阅读程序的人,这个变量不应该改变;另一个是const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;最后一个原因是 JavaScript 编译器会对const进行优化,所以多使用const,有利于提供程序的运行效率,也就是说letconst的本质区别,其实是编译器内部的处理不同。

    复制代码
    // bad
    var a = 1, b = 2, c = 3;
    
    // good
    const a = 1;
    const b = 2;
    const c = 3;
    
    // best
    const [a, b, c] = [1, 2, 3];
    复制代码

    解构赋值

    1.使用数组成员对变量赋值时,优先使用解构赋值。

    复制代码
    const arr = [1, 2, 3, 4];
    
    // bad
    const first = arr[0];
    const second = arr[1];
    
    // good
    const [first, second] = arr;
    复制代码

    2.函数的参数如果是对象的成员,优先使用解构赋值。

    复制代码
    // bad
    function getFullName(user) {
      const firstName = user.firstName;
      const lastName = user.lastName;
    }
    
    // good
    function getFullName(obj) {
      const { firstName, lastName } = obj;
    }
    
    // best
    function getFullName({ firstName, lastName }) {
    }
    复制代码

    3.如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值。(因为数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。)

    复制代码
    // bad
    function processInput(input) {
      return [left, right, top, bottom];
    }
    
    // good
    function processInput(input) {
      return { left, right, top, bottom };
    }
    
    const { left, right } = processInput(input);
    复制代码

    数组

    1.使用扩展运算符(...)拷贝数组。

    复制代码
    // bad
    const len = items.length;
    const itemsCopy = [];
    let i;
    
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    // good
    const itemsCopy = [...items];
    复制代码

    2.使用Array.from方法,将类似数组的对象转为数组。(包括ES6新增的数据结构Set和Map)

    const foo = document.querySelectorAll('.foo');
    const nodes = Array.from(foo);

    函数

    简单的、单行的、不会复用的函数,建议采用箭头函数。如果函数体较为复杂,行数较多,还是应该采用传统的函数写法。

    1.立即执行函数可以写成箭头函数的形式。

    (() => {
      console.log('Welcome to the Internet.');
    })();

    2.那些需要使用函数表达式的场合,尽量用箭头函数代替。因为这样更简洁,而且绑定了this。

    复制代码
    // bad
    [1, 2, 3].map(function (x) {
      return x * x;
    });
    
    // good
    [1, 2, 3].map((x) => {
      return x * x;
    });
    
    // best
    [1, 2, 3].map(x => x * x);
    复制代码

    3.箭头函数取代Function.prototype.bind,不应再用self/_this/that绑定 this。

    复制代码
    // bad
    const self = this;
    const boundMethod = function(...params) {
      return method.apply(self, params);
    }
    
    // acceptable
    const boundMethod = method.bind(this);
    
    // best
    const boundMethod = (...params) => method.apply(this, params);
    复制代码

    4.不要在函数体内使用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('');
    }
    复制代码

    Map结构

    注意区分Object和Map,只有模拟现实世界的实体对象时,才使用Object。如果只是需要key: value的数据结构,使用Map结构。因为Map有内建的遍历机制。

    复制代码
    let map = new Map(arr);
    
    for (let key of map.keys()) {
      console.log(key);
    }
    
    for (let value of map.values()) {
      console.log(value);
    }
    
    for (let item of map.entries()) {
      console.log(item[0], item[1]);
    }
    复制代码

    Class

    用Class,取代需要prototype的操作。因为Class的写法更简洁,更易于理解。

    复制代码
    // bad
    function Queue(contents = []) {
      this._queue = [...contents];
    }
    Queue.prototype.pop = function() {
      const value = this._queue[0];
      this._queue.splice(0, 1);
      return value;
    }
    
    // good
    class Queue {
      constructor(contents = []) {
        this._queue = [...contents];
      }
      pop() {
        const value = this._queue[0];
        this._queue.splice(0, 1);
        return value;
      }
    }
    复制代码

    使用extends实现继承,因为这比ES5的通过修改原型链实现继承,要清晰和方便很多。

    复制代码
    // bad
    const inherits = require('inherits');
    function PeekableQueue(contents) {
      Queue.apply(this, contents);
    }
    inherits(PeekableQueue, Queue);
    PeekableQueue.prototype.peek = function() {
      return this._queue[0];
    }
    
    // good
    class PeekableQueue extends Queue {
      peek() {
        return this._queue[0];
      }
    }
    复制代码

    再来看一个react中的常见例子:

    复制代码
    class ReactCounter extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 0
        };
      }
    }
    复制代码

    可以看到里面有一个constructor方法,这就是构造方法;而super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。

    这里做点补充:ES5的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this

    模块

    1.使用import取代require

    复制代码
    // bad
    const moduleA = require('moduleA');
    const func1 = moduleA.func1;
    const func2 = moduleA.func2;
    
    // good
    import { func1, func2 } from 'moduleA';
    复制代码

    2.使用export取代module.exports

    复制代码
    // commonJS的写法
    var React = require('react');
    
    var Breadcrumbs = React.createClass({
      render() {
        return <nav />;
      }
    });
    
    module.exports = Breadcrumbs;
    
    // ES6的写法
    import React from 'react';
    
    class Breadcrumbs extends Component {
      render() {
        return <nav />;
      }
    }  //这里不要加逗号
    
    export default Breadcrumbs
    复制代码

    其它

    ES6里面还要很多比较重要的概念,特别是Generator函数,Promise对象等,个人认为在node开发使用它们是非常友好的。日后若水平提高了再来叙谈。 

  • 相关阅读:
    Unity 游戏性能优化 学习
    常用网站
    Unity3d插件开发与SDK对接实战 学习
    Unity3D常用网络框架与实战解析 学习
    问题:grid卸载后重新安装时ASM磁盘识别不到了
    问题:oracle 12c rac数据库服务器的home目录丢失问题解决2018-06-25 18:30
    Linux启动报:UNEXPECTED INCONSISTENCY: RUN fsck MANUALLY问题解决
    linux下网卡bonding配置(转)
    热扩容LVM形式的/(根)分区(无损增大、缩小LVM分区)
    LVM逻辑卷管理
  • 原文地址:https://www.cnblogs.com/hehheai/p/6513991.html
Copyright © 2011-2022 走看看