JavaScript继承为什么要用中间函数F?

link
  • 22
function inherits(Child, Parent) {
    var F = function () {};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
}

1.这里的F(),有人说是为了避免继承父类的属性,但是继承不就是为了继承父类的属性和方法吗,为什么要避免?
还是说只针对下面这种有参构造器初始化的属性?

function Parent(name){
    this.name = name;
}
function Child(){}
Child.prototype = new Parent("parentName");
Child.prototype.constructor = Child;

2.如果用Object.create,就不用F()了吧?

function inherits(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
}

那这样的应该怎么继承?我不解的是这个构造器里的属性要不要继承,是按需要来,还是有什么指导思想?
因为看到的一些文章里有“不要构造器里的属性更干净、更好”的态度。

function Parent(){
    this.name = "defaultName";
}
回复
阅读 1.1k
3 个回答

我不知道为什么会有 避免继承父类的属性 这种说法,属性必须继承 属性必须继承 属性必须继承
javascript原理来看,中间方法是为了避免引用
其实很容易看出来,对比一下二者的区别就知道了

function Parent(name) {
  this.name = 123
}
Parent.prototype.show = function (){
  console.log(this.name)
}

假如不使用中间函数呢:

function Child(name) {
  Parent.call(this, name)
}
Child.prototype = Parent.prototype

这时候能看出问题吗?
如果我修改 Child.prototype 是会出问题的

Child.prototype.clear = function () {
  this.name = ''
}

你会发现 Parent 怎么也有了一个 clear 方法,子类的修改影响到父类了
这就是javascript的对象引用

这时候我们怎么避免,有两种情况,

  1. 使用中间函数(相当于创建一个新对象)
  2. 使用 Object.create()

这两种归根结底都是解决引用问题,原理都是创建一个新对象,让 Child 继承这个新对象

所以你发的两个方法根本没有区别

只不过一个是 Object.create 这个api没出来之前,老的写法用中间函数,新的就用新的Object.create写法


属性继承是必须的 并没有避免继承属性这个说法,光继承方法,不继承属性不报错?

属性继承就是另一种方法了,你发的方法,缺失了属性继承这一块,对于js的函数类来说,属性继承就是调用一下这个函数改变一下this。

function Child(name){
  Parent.call(this, name)
}

问题1
加上一个F,只是为了避免继承Parent的实例属性(也就是name),只是为了继承原型方法
问题2
如果只是单纯的只继承原型的话,可以使用Object.create(Parent.prototype)

  1. 个人认为加个F是避免原型之间的引用,另一个好处是避免重复调用父级构造函数

    function Parent(){
    }
    function Child(){
    }
    Child.prototype = Parent.prototype
    var child = new Child()
    var parent = new Parent()
    child.__proto__.say = function(){console.log(1122)}
    parent.say() // 1122
  2. Object.create的模拟实现其实就是利用中介函数

    function createObj(o) {
     function F(){}
     F.prototype = o;
     return new F();
    }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏