【问题标题】:Simpler JavaScript inheritance without duplicate code没有重复代码的更简单的 JavaScript 继承
【发布时间】:2014-11-10 16:32:21
【问题描述】:

我一直在为 JavaScript 对象/类继承而苦苦挣扎。我也不喜欢我能找到的所有示例中的重复代码(对象名称需要写几次)。

据我了解,JavaScript 中的正确继承如下所示:

function Parent(v) {
    console.log('Parent', v);
}
Parent.prototype.helloParent = function() {
    console.log('hello parent');
}


function Child(v) {
    Parent.call( this, 'from child');

    console.log('Child');
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
Child.prototype.helloChild = function() {
    console.log('hello child');
}


c = new Child();

console.log(c instanceof Child);

c.helloParent();
c.helloChild();

在这个例子中,为了扩展“Parent”对象,我必须写“Child”四次,“Parent”两次。我想只输入一次——因为DRY

我也不想为这个继承的东西定义一个自定义函数。我觉得很奇怪,需要一个用户函数来实现这样一个基本功能(而且阅读未知代码变得越来越困难,因为你永远不知道这个特定的继承函数到底在做什么)。

所以我试图找到一个更简单的版本。但是我不确定我是否错过了什么?

function Parent(v) {
    console.log('Parent', v);

    this.helloParent = function() {
        console.log('hello parent');
    }
}


(Child = function(v) {
    this.constructor('from child');

    console.log('Child');

    this.helloChild = function() {
        console.log('hello child');
    }
}).prototype = Parent.prototype;


c = new Child();

console.log(c instanceof Child);

c.helloParent();
c.helloChild();

这样可以吗?还是有严重的缺点?

编辑:关于 cmets,遗憾的是它似乎有一些严重的缺点。有没有其他的方案可以减少至少多次写入父对象的名字?

【问题讨论】:

标签: javascript class oop inheritance prototype


【解决方案1】:

我使用两个非常小的函数来简化 JavaScript 中的继承:

function defclass(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

function extend(constructor, keys) {
    var prototype = Object.create(constructor.prototype);
    for (var key in keys) prototype[key] = keys[key];
    return defclass(prototype);
}

用法如下:

var Parent = defclass({
    constructor: function (a) {
        console.log("Parent", a);
    },
    helloParent: function () {
        console.log("helloParent");
    }
});

var Child = extend(Parent, {
    constructor: function () {
        Parent.call(this, "fromChild");
        console.log("Child");
    },
    helloChild: function () {
        console.log("helloChild");
    }
});

最后:

var child = new Child;
console.log(child instanceof Child);
child.helloParent();
child.helloChild();

把它们放在一起:

function defclass(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

function extend(constructor, keys) {
    var prototype = Object.create(constructor.prototype);
    for (var key in keys) prototype[key] = keys[key];
    return defclass(prototype);
}

var Parent = defclass({
    constructor: function (a) {
        console.log("Parent", a);
    },
    helloParent: function () {
        console.log("helloParent");
    }
});

var Child = extend(Parent, {
    constructor: function () {
        Parent.call(this, "fromChild");
        console.log("Child");
    },
    helloChild: function () {
        console.log("helloChild");
    }
});

var child = new Child;
console.log(child instanceof Child);
child.helloParent();
child.helloChild();

希望对您有所帮助。

【讨论】:

  • 我不明白为什么 JS 不提供自己的构造来使继承更容易理解,并且作为代码更具可读性。
  • 这个问题的简短回答是 JavaScript 是一种设计糟糕的编程语言。幸运的是,负责设计该语言的人员是aware of this problem and are fixing it --- 尽管修复程序在很长一段时间内都不会发布。如果你想了解更多关于 JavaScript 继承的知识,那么你应该阅读我的博文:aaditmshah.github.io/why-prototypal-inheritance-matters
【解决方案2】:

javascript 中的 oop 很丑陋。 (至少在支持类和实现关键字的 ES6 之前)但即使 ES6 也不支持多重继承。我为 javascript 编写了 a small class library (available on github),这使得创建类和继承更容易开发和维护。例如要创建一个类,只需这样做:

ds.make.class({
    type: 'a',
    constructor: function (x) { this.val = x; },
    mul: function (s) {
        this.val *= s;
        return this;
    }
});

// now to inherit class a just do this...
ds.make.class({
    type: 'b',
    inherits: a,              
    constructor: function (x) { this.val = x; },
    sub: function (s) {
        this.val -= s;
        return this;
    }
});
var o = new b(5);
var output = o.mul(3).sub(5).val;    // output = 10

【讨论】:

  • 我只是在想是否可以为这些 OOP 东西定义自己的函数,但让它们的外观和感觉类似于 ES6 的功能?或者是否已经有一些跨不同框架的标准定义了
  • 没有我知道的标准,但由于可读性,许多人更喜欢这种方法……一旦 ES6 可用,它将成为标准,但要成为大多数标准还需要很多年的用户运行支持 es6 的浏览器。可能到 2017 年 es6 将成为 javascript 类的标准
猜你喜欢
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2012-06-02
  • 2013-11-30
  • 1970-01-01
  • 1970-01-01
  • 2013-03-10
相关资源
最近更新 更多