es6中的class

前言

es6的class实际上是构造函数的语法糖,可是又有区别,下面来详细分析下classjavascript

定义

先来看下class的定义的代码java

class Point{
     constructor(){}
     toString(){}
   }
   var p = new Point()
   p.constructor === Point.prototype.contructor//true
   Object.keys(Point.prototype)//[]
   Object.getOwnPropertyNames(Point.prototype)//['constructor','toString']

区别

  1. 在类的实例上调用方法,就是调用类的原型上的方法,可是类内部的方法是不可枚举的,构造函数的方法是可枚举的(是否可被for...in遍历,object.keys),构造函数能够遍历除contructor以外的方法
  2. constructor是类默认的方法,经过new生成实例时自动调用该方法,若是没有被显示定义,这个方法会被自动建立。
  3. 类只能经过new生成实例对象,若是像直接调用class会报错。
  4. 类的全部实例共享一个原型对象
    p2.__proto__ === p1.__proto__;//true
    这也就意味着能够经过实例的__proto__属性为class添加方法,不推荐使用,由于会影响到其余实例
  5. class不存在变量提高,这个和继承有关,必须保证子类在父类以后定义
  6. 类和模块内部默认都是使用严格模式
  7. class能够自定义原生数据结构(Array,String等)的子类,这是es5没法作到的,由于es5是先新建子类的this,再将父类的属性添加到子类上,因为父类的内部属性子类没法获取,致使没法继承原生的构造函数

继承

子类必须在constructor中调用super方法,不然新建实例会报错,由于子类没有本身的this,而是继承了父类的this,这和es5中的继承不同,
由于es5中的继承是先创造子类的实例对象this,再将父类的方法添加到this上(parent.call(this)),es6中是先继承父类的实例对象this,而后再用子类的构造函数修改this。若是子类没有定义constructor,那么这个方法会被默认添加。
在子类的构造函数中,只有调用super关键字以后,才可以使用this关键字,不然会报错,由于子类实例的构建基于对父类实例的加工,只有super方法才能返回父类的实例。es6

prototype和__proto__
大多数浏览器的es5实现中,每个对象都有__proto__属性(IE8除外),指向对应的构造函数的prototype属性。class做为构造函数的语法糖,同时有prototype属性和__proto__属性,由于存在两条继承链。浏览器

  1. 子类的__proto__属性表示构造函数的继承,老是指向父类
  2. 子类prototype属性的__proto__属性表示方法的继承,老是指向父类的prototype属性

class的静态方法

若是在一个方法前加上static关键字,就表示该方法不会被实例继承,而是直接经过类调用,成为‘静态方法’。
看下代码数据结构

class Foo{
  static classMethod(){}
}
Foo.classMethod();
class Bar extends Foo(){
   static classMethod(){
       return super.classMethod()
   }
}
Bar.classMethod();

上面Foo类有静态方法classMethod,只能经过Foo.classMethod调用,不可经过实例调用,不然会报错,父类的静态方法可被子类继承。函数

class的静态属性

静态属性是指class自己的属性,即class.propname,而不是定义在实例对象(this)上的属性。this

class Foo{}
Foo.prop = 1;
Foo.prop //1

上面的方法能够读、写Foo类的静态属性prop,可是es6中规定,class中只有静态方法,没有静态属性es5

new.target属性

es6为new命令引入了new.target属性,返回new命令所做用的构造函数,若是构造函数不是经过new命令调用的,那么new.target会返回undefined,所以这个属性能够判断构造函数是如何被调用的prototype

相关文章
相关标签/搜索