Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES5/ES6 的继承除了写法以外还有什么区别? #15

Open
lvwxx opened this issue Jul 31, 2019 · 0 comments
Open

ES5/ES6 的继承除了写法以外还有什么区别? #15

lvwxx opened this issue Jul 31, 2019 · 0 comments
Labels
basic JavaScript basic knowledge must konw question Further information is requested

Comments

@lvwxx
Copy link
Owner

lvwxx commented Jul 31, 2019

ES6 继承

ES6 通过 class 关键字实现类,类与类之间通过 extends 关键字实现继承。

class Super {
  constructor(x,y) {
    this.x = x
    this.y = y
  }
  print() {
    console.log(this.x, this.y)
  }
}

class Sub extends Super {
  constructor(x,y) {
    super(x,y)
  }
}

const sub = new Sub(1,2)
sub.print() // 1,2

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

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

ES5 继承

ES5 没有 class关键字,通过修改原型链实现继承

function Super() {
  this.name = 'super'
}
Super.prototype.print = function() {
  console.log(this.name, this.x, this.y)
}

function Sub(x,y) {
  this.x = x
  this.y = y
}

Sub.prototype = new Super()
Sub.prototype.constructor = Sub

const sub = new Sub(1, 2)
sub.print() // super 1 2

当试图访问一个对象的属性或者方法时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

上面的代码中, 子类 Sub 的 prototype 属性指向了 Super 的实例,也就是把 Sub 的原型指向了 Super 的一个实例, 每个实例对象内部都有一个 proto 属性,指向构造函数的原型对象,这样,通过 proto 属性的指向,形成了原型链,用代码将上述关系可以表示为:

Sub.prototype.__proto__ === Super.prototype  // true
sub.__proto__ === Sub.prototype  // true

当我们调用 sub 实例的 print 方法时,首先在 sub 对象自身上查找,发现没有这个方法,就回去 sub 的构造函数原型上去查找,也就是看 Sub.prototype 对象是否存在 print 方法, 发现也没有,最后再去查询 Sub.prototype 的原型,即 Super.prototype上调用这个方法。

总结

  • Class 声明变量会进入暂时性死区, 也就是必须先声明,再使用。
  • Class 通过 extends 关键字实现继承。 ES5 通过修改原型链实现继承
  • Class 内部定义的所有方法都不可枚举,这在 ES5 中默认是可枚举的
  • Class 内部默认使用严格模式
  • 最重要的一点不同是: ES5 是先创建子类实例对象的this,然后将父类方法赋到这个this上。Class 是先在子类构造函数中用 super 创建父类实例的 this,再在构造函数中进行修改它,这个差别使得 ES6 可以继承内置对象。。
  • Class 的子类,通过 proto 属性可以直接访问到父类 如:
function Super() {
  this.name = 'super'
}
Super.prototype.print = function() {
  console.log(this.name, this.x, this.y)
}

function Sub(x,y) {
  this.x = x
  this.y = y
}

Sub.prototype = new Super()
Sub.prototype.constructor = Sub

const sub = new Sub(1, 2)
Sub.__proto__ === Function.prototype // true

class Super {}
class Sub extends Super {}
Sub.__proto__ === Super // true
@lvwxx lvwxx added basic JavaScript basic knowledge must konw question Further information is requested labels Aug 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
basic JavaScript basic knowledge must konw question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant