2012-08-15 179 views
1

我怎么能在运行时为每个实例覆盖this.property,未做一个新的类,并最终调用父doAnotherThing的Javascript原型banals:继承

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可能会或可能不会存在。

我需要这个,因为在Backbone.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 
    }); 

回答

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() { 
}; 

这种模式设置实例性能,通常的数据,在利弊tructor。而共享属性,通常的方法,继续原型。原始代码使全部为属性实例属性,因此没有可以修改的共享属性,这会导致您的更改反映在所有实例中。

+0

假设好的(第二...),我怎么能从doOneThing里面调用doAnotherThing? – Polmonino 2012-08-15 22:57:12

+0

'this.doAnotherThing()'将起作用。 – Domenic 2012-08-15 22:59:20

+0

我做你的例子(函数覆盖),这完全消灭了原来的类...意味着现有的实例调用不再工作... – Polmonino 2012-08-15 23:20:49

1

你实际上正在考虑向后。

原型就像父类一样。 这不完全,像基于类的语言父类(有很大的分歧)。
但在这种情况下,为了继承属性/方法,原型将是父类。

当您制作Foo时,Foo是您的问题中的所有意图和目的的孩子。 当你这样做:

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

constructorFooprototype,具有相同的名字覆盖了一切链。 当Foo有一种方法或在其内部的属性,THEN它看起来上游,通过其inheritance/prototype链。

所以,如果要覆盖的Foo方法/属性,那么你MUST覆盖了的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对象。