1

我如何this.property在运行时和每个实例上覆盖,而不创建一个新类并最终调用doAnotherThing父级?

var ThridPartyObject = function() {

    this.property = 'value';

    this.doOneThing= function() { /* */ }

    this.doAnotherThing= function() { /* */ }
};

没有运气:

ThridPartyObject.prototype = {

    property: 'myvalue',

    doOneThing: function() { // Override only this function and call the other
        return this.doAnotherThing();
    }

};

编辑:忘了说property可能存在也可能不存在。

我需要这个,因为在主干.js 中,我必须为我的所有模型实例定义一个自定义属性,并且某些功能应该以与原始主干不同的方式运行。下面是主干如何定义一个Backbone.Model_.extend来自 underscore.js):

  var Model = Backbone.Model = function(attributes, options) {
    var defaults;
    attributes || (attributes = {});
    if (options && options.collection) this.collection = options.collection;
    if (options && options.parse) attributes = this.parse(attributes);
    if (defaults = getValue(this, 'defaults')) {
      attributes = _.extend({}, defaults, attributes);
    }
    this.attributes = {};
    this._escapedAttributes = {};
    this.cid = _.uniqueId('c');
    this.changed = {};
    this._silent = {};
    this._pending = {};
    this.set(attributes, {silent: true});
    // Reset change tracking.
    this.changed = {};
    this._silent = {};
    this._pending = {};
    this._previousAttributes = _.clone(this.attributes);
    this.initialize.apply(this, arguments);
  };

  // Attach all inheritable methods to the Model prototype.
  _.extend(Model.prototype, Events, {
      // cut
  });
4

2 回答 2

2

如果对象是真正的“第三方”并且不受您的控制,那么它的创建者选择了与原型继承不兼容的模式(有时称为“闭包模式”)。您将无法在全局范围内覆盖ThirdPartyObject实例的任何属性,因为每个都在构造时ThirdPartyObject获取propertydoOneThingdoAnotherThing新分配给它。

在这种情况下,唯一的解决方案是创建一个新的工厂函数来包装原始函数:

function modifiedThirdPartyObjectFactory() {
    var x = new ThirdPartyObject();
    x.property = "myvalue";
    return x;
}

var mtpo = modifiedThirdPartyObjectFactory();

使用原型继承的模式将按如下方式工作

function ThirdPartyObject() {
    this.property = "value";
}

ThirdPartyObject.prototype.doOneThing = function () {
};

ThirdPartyObject.prototype.doAnotherThing = function () {
};

此模式在构造函数中设置实例属性,通常是数据。而共享属性,通常是方法,在原型上。原始代码将所有属性都设为实例属性,因此没有可以修改的共享属性会导致您的更改反映在所有实例中。

于 2012-08-15T22:47:38.350 回答
1

你实际上是在向后考虑。

原型就像父类。它与基于类的语言中的父类不完全相同(有很多差异)。
但是在这种情况下,为了继承属性/方法,原型将是父类。

当您制作Foo, Foois the child 时,出于您的问题的所有意图和目的。当你这样做时:

function Foo () { this.method = function () {}; this.property = {}; }
Foo.prototype.method = function () {};
Foo.prototype.property = {};
Foo.prototype.other_property = 3;

这类似于说:

PrototypeClass {
    public virtual property = {};
    public other_property = 3;
    public virtual method ( ) { }
}
Foo inherits BaseClass {
    public override property = {};
    public override method () {}
}

var foo = new Foo();

constructorforFoo覆盖了链中prototype同名的所有内容。当其中Foo 没有方法或属性时,会通过其inheritance/prototype链向上游查找。

所以如果你想覆盖 的方法/属性Foo,那么你必须覆盖 的实例new Foo()

你的选择几乎只是围绕Foo......构建一个包装器......比如:

function FooPlusPlus () {
    var foo = new Foo();
    foo.plus = function () { this.doSomething(); console.log(this.val); };
    foo.plusPlus = function () { foo.plus(); console.log(this.other_val); };
    return foo;
}

var fooPlusPlus = FooPlusPlus(); // ***NO NEW***

...或创建一个函数,该函数简单地扩展一个预先存在的对象(无论是“类”、“字典”、函数还是数组),并添加您想要扩展它们的任何附加属性/功能:

var extendObj = function (subject, extensions) {
    var key = "";
    for (key in extensions) { if (extension.hasOwnProperty(key)) {
        subject[key] = extensions[key];
    }}
}


var regularFoo = new Foo();

extendObj(regularFoo, { awesomeFunc : function () { if (typeof this.doSomething === "function") { this.doSomething(); }}, coolProp : "Bob" });

JS 让您可以自由地让任何东西继承任何东西,只要您不期望字符串或数字像具有自定义数据的类一样,无需仔细操作 Core 对象。

于 2012-08-15T23:16:09.377 回答