如何在JavaScript中制作原型原型?

时间:2014-07-08 01:29:49

标签: javascript prototype

我正在尝试用Javascript创建原型的原型。使用从头开始构建的普通原型,而不是以下功能,我希望我的原型继承某些方法,而不是将它们添加到每个方法中。

因此,我在原型中添加了方法logDependencies()而不是此代码,以检查Dependency实例中是否存在Car的任何实例:

function Dependency(data) {
    this.data = data;
}

function Car(color) {
    this.color = new Dependency(color);

    this.logDependencies = function () {
        for (var key in this)
            if (this.hasOwnProperty(key))
                if (this[key] instanceof Dependency)
                    console.log("Dependency: " + key);
    };
}

var lamborghini = new Car("red");

lamborghini.logDependencies();

我想让我的所有原型继承函数logDependencies(),而不是我手动添加它。

我该怎么做?


更新

对于那些因我的措辞而感到困惑的人:

我正在尝试制作一个原型设计功能,它允许我创建继承某些属性和方法的原型,并将它们传递给继承链。

Douglas Crockford撰写的一篇相关文章(强调我自己):

  

我的旅程迂回曲折,因为JavaScript本身就其原型性质而言存在冲突。在原型系统中,对象从对象继承。但是,JavaScript缺少执行该操作的运算符。相反,它有一个新的运算符,以便new f()生成一个继承自f.prototype的新对象。

     

这种间接性旨在使语言对于经过专业训练的程序员来说更为熟悉,但却未能做到这一点,正如我们从Java程序员对JavaScript的非常低级的看法中看到的那样。 JavaScript的构造函数模式并没有吸引经典人群。它还掩盖了JavaScript真正的原型性质。因此,很少有程序员知道如何有效地使用该语言。

     

幸运的是,很容易创建一个实现真正原型继承的运算符。这是我工具包中的标准功能,我强烈建议您使用它。

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}
     

对象函数解开JavaScript的构造函数模式,实现真正的原型继承。它将旧对象作为参数,并返回一个从旧对象继承的空对象。如果我们尝试从新对象获取成员,并且它缺少该键,则旧对象将提供该成员。对象继承自对象。什么可能比这更面向对象?

     

因此,不是创建类,而是创建原型对象,然后使用object函数创建新实例。对象在JavaScript中是可变的,因此我们可以扩充新实例,为它们提供新的字段和方法。然后,这些可以作为更新对象的原型。我们不需要类来制作许多类似的对象。

     

为方便起见,我们可以创建将为我们调用对象函数的函数,并提供其他自定义,例如使用特权函数扩充新对象。 我有时称这些制造商的功能。如果我们有一个调用另一个制造商函数而不是调用对象函数的制造商函数,那么我们就有一个寄生继承模式。

     

我发现通过使用这些工具,结合JavaScript的lambdas和对象准文字,我可以编写结构良好的大型,复杂和高效的程序。经典对象模型是目前最流行的对象模型,但我认为原型对象模型更有能力并且提供更具表现力的功能。

3 个答案:

答案 0 :(得分:1)

听起来你只是想加入汽车的原型?或者您想将它添加到您创建的所有的原型中(不明智)?

car.prototype.logDependencies = function(){ return 'whatever'; }

var lamborghini = new car('red');

lamborghini.logDependencies(); // whatever 

以下是您如何让一个体面的JavaScript开发人员生气:

Object.prototype.logDependencies = function(){ return "I just don't give a..."; }

var anything = new Object();

anything.logDependencies(); // I just don't give a...

澄清一下,上述不好的原因在您发布的文章中有解释:

  

对象函数的问题在于它是全局的,而且是全局的   显然有问题。 Object.prototype的问题。[someMethod]   是它绊倒了无能的程序,它可以产生   

读完你的评论后,听起来好像你是在追逐各种魔杖。也许你来自Java世界?还是一个Actionscript 3世界?类型更强,遗传是经典的。 JavaScript是一种非常具有可塑性的语言,我们都设法以某种形式或其他方式挤出其他语言的各个方面。但是,如果你要求JavaScript做的是强制执行某种基于类的继承系统,而不需要调用一些方法并在这里声明一些变量,那么你就会感到失望。

我建议你阅读道格拉斯·克罗克福德的other article,其中他解释了JavaScript的原型系统是多么有用 - 并暗示如何利用经典的继承性特征。

答案 1 :(得分:0)

如果您希望继承行中car具有parent原型的所有函数,那么您可以使用:

car.prototype = Object.create(parent.prototype);

基本上,Object.create(obj)返回一个新对象,其原型设置为objcar的所有实例都将其原型设置为car.prototype。因此,他们可以通过原型链访问parent的函数。

答案 2 :(得分:0)

您可以随时使用mixins进行共享功能。例如:

var mixinLogger = (function () {
    return function (that) {
        that.logDependencies = logDependencies;
        return that;
    };

    function logDependencies() {
        for (var key in this)
            if (this.hasOwnProperty(key) &&
                this[key] instanceof Dependency)
                console.log("Dependency: " + key);
    }
}());

您可以按如下方式使用它:

function Dependency(data) {
    this.data = data;
}

function Car(color) {
    this.color = new Dependency(color);
}

mixinLogger(Car.prototype);

使用mixins的优点是它们是可组合的。例如,如果您有两个mixins(mixinAmixinB),那么您可以按如下方式链接它们:

mixinA(mixinB(Something.prototype));

你甚至可以创建一个新的mixin,它是两者的组合:

function compose() {
    var fs = arguments;
    var length = fs.length;

    return function (x) {
        var index = length;
        while (index > 0) x = fs[--index](x);
        return x;
    };
}

var mixinC = compose(mixinA, mixinB);

事实上,你可以根据自己的意愿创作尽可能多的混音,以创造新的混音。

如果您想了解更多信息,请阅读博客文章" A fresh look at JavaScript Mixins"。