从子对象修改原型上的字段

Modifying a field on a prototype from a child object

本文关键字:字段 原型 修改 对象      更新时间:2023-09-26

这是一个清洁的问题。

我使用原型来实现基本的继承,以保持我的代码DRY,我有一些原型,这是为了所有的意图和目的抽象(它不期望它们将被实例化之外被设置为其他对象的原型),他们包含一些代码,"子"对象将调用。问题是原型中的函数依赖于原型的一些字段。更新子对象上的字段显然不会修改原型的字段。我想避免调用

childObject.prototype.field = foo;

,因为继承越深就越混乱。

下面我粘贴了一个例子来解释我要做的事情。你可以看到它在jsfiddle上运行。

//Prints something once.
function Printer(text) {
    this.text = text || "";
    this.print = function () {
        alert(text);
    };
}
//Prints everything a set number of times
function AnnoyingPrinter(text, count) {
    this.prototype = new Printer(text);
    this.count = count || 1;
    this.print = function () {
        for (var i = 0; i < this.count; i++) {
            this.prototype.print();
        }
    };
}
function doStuff() {
    var annoyer = new AnnoyingPrinter("Hello world!", 2);
    annoyer.print();
    //Now I want to change the text without having to dig down into the prototype     (particularly if I ever want to extend AnnoyingPrinter too)
    annoyer.text = "Goodbye world!";
    annoyer.print();
}
//Expected outcome:
//Hello world!
//Hello world!
//Goodbye world!
//Goodbye world!

//Actual outcome:
//Hello world!
//Hello world!
//Hello world!
//Hello world!
doStuff();

这是原型继承的典型模式。

function Printer(text) {
    this.text = text || "";
}
Printer.prototype.print = function() {
    alert(this.text);
}
function AnnoyingPrinter(text, count) {
    Printer.call(this, text);
    this.count = count || 1;
}
AnnoyingPrinter.prototype = Object.create(Printer.prototype);
AnnoyingPrinter.prototype.printAll = function() {
    for (var i = 0; i < this.count; i++) {
        this.print();
    }
}

那么你的doStuff()可以继续创建一个新的AnnoyingPrinter,并命名为print()

function doStuff() {
    var annoyer = new AnnoyingPrinter("Hello world!", 2);
    annoyer.printAll();   // "Hello world!" "Hello world!"
    annoyer.text = "Goodbye world!";
    annoyer.printAll();   // "Goodbye world!" "Goodbye world!"
}

演示: http://jsfiddle.net/DhbgE/

我只需要改变它,使两个构造函数有不同的方法名。如果我们给AnnoyingPrinter一个.print()方法,它会遮蔽Printer的方法。

将属性存储在本地对象中,并在原型函数中引用它们。你不希望在原型对象中保留状态,这应该只用于函数(或者必要时"静态"字段)。

http://jsfiddle.net/C7aPQ/2/

//Prints something once.
function Printer(text)
{
    this.text = text || "";
    this.print = function()
    {
        alert(this.text);
    };
}
//Prints everything a set number of times
function AnnoyingPrinter(text,count)
{
    this.prototype = new Printer(text);
    this.text = text;
    this.count = count || 1;
    this.print = function()
    {
        for(var i =0;i<this.count;i++)
        {
            this.prototype.print.call(this);
        }
    };
}