Class

ES6 的类其实是原型继承的语法糖:

当我们尝试用 class 去定义一个 Dog 类时:

class Dog {
  constructor(name ,age) {
   this.name = name
   this.age = age
  }
  
  eat() {
    console.log('肉骨头真好吃')
  }
}

其实完全等价于写了这么一个构造函数:

function Dog(name, age) {
  this.name = name
  this.age = age
}

Dog.prototype.eat = function() {
  console.log('肉骨头真好吃')
}

类的数据类型就是函数,类本身就指向构造函数。

不存在变量提升(hoist)

类不存在变量提升

私有方法

命名区分

一种做法是在命名上加以区别。

上面代码中,_bar方法前面的下划线,表示这是一个只限于内部使用的私有方法。但是,这种命名是不保险的,在类的外部,还是可以调用到这个方法。

call调用

上面代码中,foo是公开方法,内部调用了bar.call(this, baz)。这使得bar实际上成为了当前模块的私有方法。

Symbol 值

Symbol值。

上面代码中,barsnaf都是Symbol值,

继承

子类必须在constructor方法中调用super方法

上面代码中,constructor方法和toString方法之中,都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。

子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

只有调用super之后,才可以使用this关键字

这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例。

上面代码中,子类的constructor方法没有调用super之前,就使用this关键字,结果报错,而放在super方法之后就是正确的。

super 作为函数调用时代表父类的构造函数

上面代码中,子类B的构造函数之中的super(),代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。

super 作为对象时在普通方法中指向父类的原型对象。

上面代码中,子类B当中的super.p(),就是将super当作一个对象使用。这时,super在普通方法之中,指向A.prototype,所以super.p()就相当于A.prototype.p()

这里需要注意,由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。

上面代码中,p是父类A实例的属性,super.p就引用不到它。

最后更新于

这有帮助吗?