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

JS继承的方式以及优缺点 #60

Open
xiaochengzi6 opened this issue Oct 18, 2022 · 1 comment
Open

JS继承的方式以及优缺点 #60

xiaochengzi6 opened this issue Oct 18, 2022 · 1 comment
Labels
JavaScript JavaScript 语言的学习

Comments

@xiaochengzi6
Copy link
Owner

主要参考这篇文章js继承的多种方式及优缺点

前置条件,js 继承中对象是由构造函数通过 new 调用创建的,那么继承就需要两个构造函数后者去继承前者,分别称之为子类和父类

原型链继承

缺点:

  1. 继承后的属性要是引用类型修改子类父类中的属性也会改变
  2. 创建子类时不能向父类传递参数

借用构造函数

优点:

  1. 继承的属性是引用类型修改子类并不会影响到父类
  2. 可以向父类传递参数

缺点:

  1. 方法都要在构造函数上定义每一次 new (创建对象) 都要重新创建一遍方法

组合继承

优点:

  1. 通过组合继承可以避免上述缺点并且具有上述的优点

组合继承最大的缺点是会调用两次父构造函数。

原型式继承

function createObj(obj){
  function f(){}
  f.prototype = new obj()
  return new f()
}

缺点:

  1. 包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承一样

寄生式继承

function createObj(obj){
  var obj = Object.create(obj)
  obj.sayName = function () {}
  return obj
}

**缺点:**跟借用构造函数模式一样,每次创建对象都会创建一遍方法。

寄生组合式继承

var parent = new function A () {}
var child = new function B () {}

child.prototype = Object.create(patent.prototype)

重点在于:(参考组合继承代码)如果我们不使用 Child.prototype = new Parent() ,而是间接的让 Child.prototype 访问到 Parent.prototype
也就是这样的效果

var parent = new function A () {}
var child = new function B () {}

function c () {}
c.prototytpe = patent.prototype
child.prototype = new c

也就是说在中间做了一次转发从而去继承 parent 原型 抛弃它定义在自身的属性

总结:这种方式的高效率体现它只调用了一次 Parent 构造函数,并且因此避免了在 Parent.prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变

@xiaochengzi6 xiaochengzi6 added the JavaScript JavaScript 语言的学习 label Oct 18, 2022
@xiaochengzi6
Copy link
Owner Author

xiaochengzi6 commented Oct 18, 2022

ES5 中的继承

ES5 中继承机制是先创建一个独立的子类的实例对像,然后再将父类的方法添加到这个对象上面 实例在前,继承在后的特点
这个性质非常像 new 的调用方式 下面实现一下 new

function myNew (obj){
  var newObj = {}
  newObj.prototype = obj.prototype
  var result = newObj.call(this)
  return result || newObj
}

ES6 中的继承机制

先将父类的属性和方法加载到空对象上,然后再将该对象作为子类的实例 就是“继承在前,实例再后” 最明显的就是使用 class 中继承子类继承与父类必须在 constructor内使用 supper() 才行

class A {}
class B extends A{
  constructor(){
    supper()  
  }
}

调用supper () 会生成一个继承父类的 this 对象所以才能继承父类

es6 实际上是新建了一个 对象 (对象的this 是父类的)也就是说这个对象会拥有父类的所有属性和方法(换句话说是父类的this对象 因为可以通过 this 访问到所有的属性和方法),再通过子类的构造函数中去修改这个 this 对象 从而完成继承

class A {}
class B extends A {
  constructor (...args) {
    supper(...args)
    // 从这里开始就可以操作 this 来修改父类中定义的东西 (个性化子类)
  }
}

特点、差异

es5 中不能去继承原生的构造函数
image
因为无法获取到它(父类)的内部属性从而不能创建和父类一样的子类

function A (){
  Array.call(this)
}
var a = new A()

值得注意的是 这些原生构造函数会忽略 call apply 绑定的 this 原生构造函数的this无法绑定,导致拿不到内部属性

主要就是和 es5 中的继承机制有关,es5 会创建一个对象 再将父类的属性添加到子类上,由于无法获取父类的内部属性从而无法继承

但是 es6 可以 它就是使用 父类的this对象 然后在子类的构造函数中去修改父类的属性或者方法

因为 ES6 是先新建父类的实例对象this,然后再用子类的构造函数修饰this,使得父类的所有行为都可以继承

class A extends B {
  constructor(..args){
    supper(...args)
  } 
}

主要参考文章:阮一峰 es6 入门

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JavaScript JavaScript 语言的学习
Projects
None yet
Development

No branches or pull requests

1 participant