ES5 构造函数与ES6 Class的区别

  • Class 类中不存在变量提升
    // es5
        var bar  = new Bar(); // 可行
        function Bar() {
            this.bar = 42;
        }
    
    //es6
        const foo = new Foo(); // Uncaught ReferenceError
        class Foo {
            constructor() {
                this.foo = 42;
            }
        }

  • class内部会启用严格模式
    // es5
   function Bar() {
       // 引用一个未声明的变量
       baz = 42; // it's ok
   }
   var bar  = new Bar(); 

   // es6
   class Foo {
       constructor(){
           // 引入一个未声明的变量
           fol = 42;// Uncaught ReferenceError: fol is not defined
       }
   }
   let foo = new Foo();

  • class的所有方法都是不可枚举的
  // es5
  function Bar() {}   
  Bar.answer = function () {};
  Bar.prototype.print = function () {};
  console.log(Object.keys(Bar));// ["answer"]
  console.log(Object.keys(Bar.prototype))// ["print"]
  // es6
  class Foo {
      constructor(){}
      static answer() {}
      print(){}
  }
  console.log(Object.keys(Foo))// []
  console.log(Object.keys(Foo.prototype));// []

  • class 必须使用new调用
 // es5
    function Bar(){ }
    var bar = Bar();// it's ok;
    // es6
    class Foo {

    }
    let foo = Foo();// Uncaught TypeError: Class constructor Foo cannot be invoked without 'new'

  • class 内部无法重写类名
 // es5 
    function Bar() {
        Bar = 'Baz';
        this.bar = 42;
    }
    var bar = new Bar();
    console.log(bar);// Bar {bar: 42}
    console.log(Bar);// 'Baz'

    // es6
    class Foo {
        constructor(){
            this.foo = 42;
            Foo = 'Fol'; // Uncaught TypeError: Assignment to constant variable.
        }
    }
    let foo = new Foo();
    Foo = 'Fol';// it's ok
  • class 的继承有两条继承链

一条是: 子类的__proto__ 指向父类

另一条: 子类prototype属性的__proto__属性指向父类的prototype属性.

es6的子类可以通过__proto__属性找到父类,而es5的子类通过__proto__找到Function.prototype

    // es5
    function Super() {}
    function Sub() {}
    Sub.prototype = new  Super();
    Sub.prototype.constructor = Sub;
    var sub = new Sub();
    console.log( Sub.__proto__ === Function.prototype);// true

    // es6
    class Super{}
    class Sub extends Super {}
    let sub = new Sub();
    console.log( Sub.__proto__ === Super);// true
  • es5 与 es6子类this的生成顺序不同。

es5的继承是先建立子类实例对象this,再调用父类的构造函数修饰子类实例(Surper.apply(this))。

es6的继承是先建立父类实例对象this,再调用子类的构造函数修饰this。即在子类的constructor方法中必须使用super(),之后才能使用this,如果不调用super方法,子类就得不到this对象。

  • 正是因为this的生成顺序不同,所有es5不能继承原生的构造函数,而es6可以继承
      // es5
      function MyES5Array() {
          Array.apply(this, arguments);
          // 原生构造函数会忽略apply方法传入的this,即this无法绑定,先生成的子类实例,拿不到原生构造函数的内部属性。
      }
      MyES5Array.prototype = Object.create(Array.prototype, {
          constructor: {
              value: MyES5Array,
              writable: true,
              configurable: true,
              enumerable: true
    
          }
      })
      var arrayES5 = new MyES5Array();
      arrayES5[0] = 3;
      console.log(arrayES5.length);// 0 
      arrayES5.length = 0;
      console.log(arrayES5[0]);// 3
    
      // es6
      class arrayES6 extends Array {
          constructor(...args){
              super(...args);
          }
      }
      let arrayes6 = new arrayES6();
      arrayes6[0] = 3;
      console.log(arrayes6.length);// 1
      arrayes6.length = 0;
      console.log(arrayes6[0]);// undefined

你可能感兴趣的:(es6,javascript,开发语言)