美文网首页
ES6学习笔记

ES6学习笔记

作者: 豪秋 | 来源:发表于2018-12-05 14:25 被阅读0次

    1. 变量的解构赋值

    • 数组解构
    let [a, b, c] = [1, 2, 3] // a = 1, b = 2, c = 3
    
    • 对象解构
    let {foo, bar} = {foo: 'foo', bar: 'bar'}; // foo = 'foo', bar = 'bar'
    

    2. 箭头函数,rest参数

    • 箭头函数
    var sum = (num1, num2) => num1 + num2;
    var getObj = id => ({id: id, name: 'bob'}) // 如果返回的是个对象,需要用圆括号包起来
    
    • rest 参数
    function add(...values) {
      let sum = 0;
      values.forEach(x => sum+= x);
      return sum;
    }
    add(1, 2, 3); // 6
    

    3. 数组:

    • 扩展运算符 …[] 将一个数组转换成用逗号分隔的参数序列。
      ...[1,2,3] // 1,2,3
    • Array.from() 将类似于数组的对象转换成数组。
    • Array.of() 将一组值转换成数组,
      Array.of(1,2,3) // [1,2,3]
    • filter/find/findIndex 找出符合条件的数组成员。
    • includes() 判断数组是否包含某个值
      兼容写法:
    const contains = (() => Array.prototype.includes ? (arr, value) => arr.includes(value) : arr.some(el => el === value))()
    
    • keys/values/entries 供 for of 遍历

    4. 对象

    • Object.assign() 将源对象(source)的所有可枚举属性复制到目标对象(target)。用法:
    var target = {
      a: 1
    };
    var source1 = {
      b: 2
    };
    var source2 = {
      b: 3
    }
    Object.assign(target, source1, source2) // {a:1,b:2,c:3}
    
    • Object.keys() // 返回自身所有可枚举的属性
    • Object.values()
    • Object.entries()
    • keys/values/entries
    • Object.setPrototypeOf() 用来设置一个对象的prototype对象
    • Object.setPrototypeOf(obj, prototype)
    • Object.getPrototypeOf() 用来读取对象的prototype对象

    5. Symbol 一种新的原始数据类型,表示独一无二的值。每个Symbol的值都不相等。(Symbol值不能与其他类型的值进行运算)

    var s = Symbol(’s’) 可接收一个参数,用于描述。

    • 作为属性名的Symbol,保证不会出现同名的属性。
    var mySymbol = Symbol();
    // 第一种写法
    var a = {};
    a[mySymbol] = 'hello';
    // 第二种写法
    var b = {
      [mySymbol]: 'hello'
    }
    // 第三种写法
    var c = {};
    Object.defineProperties(c, mySymbol, {
      value: 'hello'
    });
    // 注意:Symbol值作为对象属性名时,不能使用点运算符
    

    6. Set和Map数据结构

    - Set——类似于数组,成员没有重复

    数组去重:
    [...new Set([1,2,3,4,4])] // [1,2,3,4]或者 Array.from(new Set([1,2,2,3,3]));

    • Set实例的属性和方法
      • add(value): 添加某个值,返回Set本身。
      • delete(value):删除某个值
      • has(value):返回一个布尔值,表示参数是否为Set的成员。
      • clear():清除所有成员
    let mySet = new Set();
    mySet.add(1).add(2).add(2);
    s.size // 2
    s.has(1) // true
    s.has(2) // false
    s.delete(2);
    s.has(2); //  false
    

    数组的map和filter也适用于Set,因此使用Set可以很容易的实现并集(Union)、交集(Intersect)、差集(Difference)。

    let a = new Set([1,2,3]);
    let b = new Set([2,3,4]);
    // 并集
    let union = new Set([...a,...b]); //set {1,2,3,4}
    // 交集
    let intersect = new Set([...a].filter(x => b.has(x))); //set {2,3};
    // 差集
    let differenceA = new Set([...a].filter(x => !b.has(x))); // set{1}
    let differenceB = new Set([...b].filter(x => !a.has(x))); // set{4};
    let difference = new Set([...differenceA,...differenceB]); // set{1,4};
    
    - Map——类似于对象,也是键值对的集合,各种类型的值都可以当做键,即“值——值”。
    • Map实例的属性和方法
      • set(key, value)
      • get(key)
      • delete(key):删除某个值
      • has(key):返回一个布尔值,表示参数是否为Map的成员。
      • clear():清除所有成员
        Map结构转为数组,可使用拓展运算符 ... ,如
    let map = new Map([
      [1,'one'],
      [2,'two'],
      [3, 'three']
    ])
    [...map.keys()] // [1,2,3]
    [...map.values()] // ['one','two','three']
    [...map] // [[1,'one'],[2,'two'],[3,'three']]
    

    结合数组的map方法、filter方法,可以实现Map的遍历和过滤。

    [...map].filter(([k, v]) => k < 2); // map {1 => 'a'}
    

    7. Proxy-代理、拦截

    Proxy可以理解成为目标对象前架设一个“拦截”层,外界对改对象的访问都必须先通过这层拦截,可以对外界的访问进行过滤和改写。

    let proxy = new Proxy(target, handler)
    

    target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。

    var proxy = new Proxy({}, {
      get(target, property) { // target 表示 目标对象,property所要访问的属性
        return 35;
      }
    })
    
    proxy.time // 35
    proxy.title // 35
    

    注意:
    要使Proxy起作用,必须针对proxy实例。

    • Proxy实例的方法
      • get():用于拦截某个属性的读取操作
    var person = {
      name: '张三'
    }
    var personProxy = new Proxy(person, {
      get(target, property){
        if(property in target){
          return target[property];
        }else{
           throw new Error('...');
        }
      }
    })
    personProxy.name // 张三
    personProxy.age // 报错
    
    • set():用于拦截某个属性的赋值操作
    let validator = {
      set(obj, prop, value) {
        if (prop === 'age') {
          if (!Number.isInteger(value)) {
            throw new TypeError('The age is not an integer');
          }
          if (value > 200) {
            throw new RangeError('The age seems invalid');
          }
          obj[prop] = value;
        }
      }
    };
    let person = new Proxy({}, validator);
    person.age = 100; // 100
    person.age = 'young'; // 报错
    person.age = 300; // 报错
    

    8. Promise对象——异步编程的解决方案

    var getJson = function(url) {
      var promise = new Promise(function(resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open('get', url);
        xhr.responseType = 'json';
        xhr.setRequestHeader('Accept', 'application/json');
        xhr.send();
        xhr.onreadystatechange = function() {
          if (this.readyState !== 4) {
            return;
          }
          if (this.status === 200) {
            resolve(this.response);
          } else {
            reject(new Error(this.statusText));
          }
        };
        return promise;
      });
    };
    
    getJson('data.json')
      .then(json => {
        console.log('json' + json);
      })
      .catch(e => {
        console.log(e);
      });
    
    

    注:promise先记录个简单用法,后期再深入学习。

    9.Class

    es5通过构造函数定义并生产对象,如:

    function Point(x, y) {
      this.x = x;
      this.y = y;
    }
    
    Point.prototype.toString = function() {
      return `(${this.x}, ${this.y})`;
    };
    

    ES6引入了Class(类)的概念作为对象的模板,通过class关键字定义类,通过class改写上面的Point类。

    class Point {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
      toString() {
        return `(${this.x}, ${this.y})`;
      }
    }
    let p = new Point(1, 2); // 类必须使用new来调用
    

    类的所有方法都定义在类的prototype属性上。

    10.Class的继承

    Class通过extends实现继承。

    class Point {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
      toString() {
        return `(${this.x}, ${this.y})`;
      }
    }
    
    class ColorPoint extends Point {
      constructor(x, y, color) {
        super(x, y); // 调用父类的constructor(x, y)
        this.color = color;
      }
    
      toString() {
        return `${this.color} ${super.toString()}`; // 调用父类的toString()
      }
    }
    
    let colorPoint = new ColorPoint(2, 3, 'red');
    

    子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。在子类的构造函数中,只有调用了super之后才可以使用this关键字。

    ES5与ES6的继承

    • ES5的继承实质是先创建子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。
    • ES6实质是先创建父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。

    super虽然代表了父类的构造函数,但是返回的是子类的实例,即super内部的this指的是子类,因此super()在此相当于 父类.prototype.constructor.call(this)。

    super关键字

    • 作为函数使用,子类的构造函数必须执行一次super函数。
    • 作为对象在普通方法中指向父类的原型对象
      由于绑定子类的this,因此如果通过super对某个属性赋值,这是super就是this,赋值的属性会变成子类实例的属性。
    class A {
      constructor() {
        this.x = 1;
      }
    }
    
    class B extends A {
      constructor(){
        super();
        this.x = 2;
        super.x = 3; // super.x 等同于 this.x
        console.log(super.x); // super.x 等同于 A.prototype.x  undefined
        console.log(this.x); // 3
      }
    }
    

    11.Module语法

    ES6模块是编译时加载或者静态加载,CommonJS模块是‘运行时加载’,因此ES6模块效率更高。

    • export
    // profile.js
    let firstName = 'Michael';
    let lastName = 'Jackson';
    let year = 1958;
    function getName(firstName, lastName) {
      return `${firstName} ${lastName}`;
    }
    function v1(year) {
      return `${year}-01-01`;
    }
    export { firstName, lastName, year, getName, v1 as getDate };
    

    通常情况下,export输出的变量就是本身的名字,但也可以使用as关键字重命名。

    • import
    import {
      firstName,
      lastName,
      year
    } from './profile';
    
    function setName(ele) {
      ele.textContent = `${firstName} ${lastName}`;
    }
    

    由于import是静态执行,所以不能使用表达式。如果多次重复执行同一句import语句,只会执行一次。

    • 模块的整体加载
      除了指定加载某个输出值,还可以使用整体加载(*)来指定一个对象,所有输出值都加载在这个对象上。
    // circle.js
    function area(radius) {
      return Math.PI * radius * radius;
    }
    
    function circumference(radius) {
      return 2 * Math.PI * radius;
    }
    export {
      area,
      circumference
    }
    // 指定加载某个值
    import {area, circumference} from './circle';
    console.log(area(4));
    // 整体加载一个对象(* 重命名 circle)
    import * as circle from './circle';
    console.log(circle.area(4));
    
    • export default 默认输出

    本质上,export default 就是输出了一个叫做default的变量或方法,将该命令后面的值赋给default然后再默认,然后系统允许我们为他取名字。

    对比默认输出和正常输出

    • 默认输出:export default
    export default function foo(){
      console.log('foo');
    } // 函数名foo在模块外无效,加载时视同匿名函数
    import fn from './foo.js'
    
    • 正常输出:export
    function foo() {
      console.log('foo');
    }
    export {
      foo
    }
    from './foo.js'
    
    • export 与impor的复合用法
    export {foo, bar} from './my_module';
    // 等同于
    import {foo, bar} from './my_module';
    export {foo, bar};
    
    • import():完成动态加载,运行时执行。
      import能接受什么参数,import()就可以接受什么参数。
      import()函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。
      import()返回一个Promise对象:加载模块成功之后,会作为一个对象当做then的参数。
    import('./myModule.js')
      .then({export1, export2} => {
         // ...
      })
      .catch(e => {
       console.log(e)
      });
    

    import()的适用场景

    • 按需加载:import()可以在需要的时候加载某个模块。
    button.addEventListener('click', event => {
      import('./dialoge.js').then(dialoge => {
        dialoge.open();
      }).catch(e => {
        console.log(e);
      })
    })
    
    • 条件加载
    if(condition){
      import('moduleA').then()
    }else{
      import('moduleB').then()
    }
    

    12.编码风格

    1. 在let和const之间,建议优先使用const。
      const优于let有一下原因:

      • 提醒阅读程序的人,此变量不可改变。
      • javascript编译器会对const 进行优化。
    2. 优先使用解构赋值。

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

    4. 用Class取代需要prototype的操作。因为Class的写法更简洁。使用extends实现继承,更简单。

    5. Module语法是Javascript模块的标准写法。使用import取代require,使用export取代mudule.exports。

    相关文章

      网友评论

          本文标题:ES6学习笔记

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