繁体   English   中英

如何用JavaScript制作原型?

[英]How can I make a prototype of a prototype in JavaScript?

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

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

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)的相关文章(强调我自己):

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

这种间接作用旨在使经过经典训练的程序员对这种语言更加熟悉,但是却没有做到这一点,正如我们从Java程序员对JavaScript的极低评价中可以看到的那样。 JavaScript的构造器模式对古典人群没有吸引力。 它还掩盖了JavaScript的真正原型性质。 结果,很少有知道如何有效使用该语言的程序员。

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

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

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

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

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

我发现通过使用这些工具,再结合JavaScript的lambda和对象准文字,我可以编写结构合理的程序,这些程序既大型,复杂又高效。 迄今为止,经典的对象模型是最受欢迎的,但是我认为原型对象模型更强大,并且提供了更多的表达能力。

听起来您只是想添加到汽车原型中? 还是要将其添加到您创建的所有内容的原型中(不建议使用)?

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]的问题在于,它会触发不合格的程序,并且当[someMethod]被覆盖时,它可能会产生意外的结果。

阅读了您的评论后,对我来说听起来好像您是在追逐魔杖。 也许您来自Java世界? 还是Actionscript 3世界? 类型更强,继承是经典。 JavaScript是一种非常具有延展性的语言,我们所有人都设法以某种形式将其他语言的各个方面挤出来。 但是,如果您要JavaScript执行的是实施某种基于类的继承系统而又不调用一些方法并且不需声明一些变量的情况,那么您将感到失望。

我建议您阅读Douglas Crockford的一篇文章 ,其中他解释了JavaScript原型系统的实用性,并暗示了如何利用类似经典继承的功能。

如果您想要继承car拥有parent原型化的所有功能的继承路线,则可以使用:

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

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

您总是可以使用mixin共享功能。 例如:

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);

使用mixin的优点在于它们是可组合的。 例如,如果您有两个mixin( 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);

实际上,您可以根据需要组成任意数量的mixin,以创建新的mixin。

如果您想了解更多,那么您应该阅读博客文章“ JavaScript Mixins的新外观 ”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM