好吧,我第一次试图解释我在做什么的尝试失败了。我基本上复制了Crockford的Object.create(),除了私有变量。
如果你看一下这里接受的答案How to inherit from a class in javascript?,你会看到Object.create是最后一个模式,我认为它更符合Javascript(对象beget对象)的原型性质,而不是模仿经典继承(类生成对象)。
如果你看一下维基百科关于原型编程的文章(http://en.wikipedia.org/wiki/Prototype-based_programming),你可以看到更多我的意思。
Object.create()的缺点是不支持私有成员。这就是我的建议:
Function.prototype.from = function(obj) {
function F() {this.parent = Object(obj);}
F.prototype = obj;
var out = new F();
this.apply(out);
return out;
};
然后,您可以这样创建对象:
// Create an object
var a = function() {
var private_property = 'blue';
this.public_property = 7;
this.public_method = function() {
alert(this.public_property + ' ' + private_property);
}
}.from(null); // .from() works too, but .from(null) is more revealing
// Create a new object using 'a' as the prototype
var b = function() {
var private_property = 'red';
this.public_property = 8;
}.from(a);
// See the results
a.public_method(); // Alerts '7 blue'
b.public_method(); // Alerts '8 blue' - Parent methods use parent private variables
a.public_method = function() { alert('rabbit'); };
a.public_method(); // Alerts 'rabbit'
b.public_method(); // Alerts 'rabbit'
b.public_method = function() { alert('dog'); };
a.public_method(); // Alerts 'rabbit'
b.public_method(); // Alerts 'dog' - Parent method is overwritten
我创建“from”函数的方式是,当父对象更改其方法时,如果要阻止子实例中的更改,可以指定:
this.public_method = this.parent.public_method;
在子实例中。
还要注意,从nihilo创建的对象不会从Object继承(hasOwnProperty等等)。您必须将其明确指定为.from(Object)。
这种模式的好处:
我可以想到这种方法的一个主要缺点:'function()'语法可能会让人误以为将函数分配给变量而不是对象。
我的问题是,我还有其他缺点吗? (不要包括原型模式的缺点 - 这是主观的 - 但仅限于我的实现)。
答案 0 :(得分:1)
首先,如前所述,Function.prototype
方法确实很痛苦。为什么不实现这样的事情:
Object.createChild = function(obj, constructor) {
function F() { this.parent = Object(obj); }
F.prototype = obj;
var out = new F();
if (typeof constructor == 'function') {
constructor.apply(out);
}
return out;
};
然后使用
var a = Object.createChild(null, function () { /*...*/ });
var b = Object.createChild(a, function () { /*...*/ });
与上述结果相同。
额外奖励:您可以省略constructor
参数,如下所示:
var c = Object.createChild(anything);
其次,我不知道是否有任何用于真正的原型继承的东西,就像你所说的那样。在现实生活中,我非常确定构造函数特别适合于即将扩展的对象(a
)。因此,你最终会打电话给
var x = f.from(a);
var y = f.from(a);
一遍又一遍地使用f
- a
组合。是的,与类驱动的方法相比,你节省了一些字节的内存,但老实说,谁在乎呢?
然而,理论上整个事情都是一个非常好的主意。