Javascript继承理念(第2部分)

Nic*_*ick 8 javascript inheritance prototype

好吧,我第一次试图解释我在做什么的尝试失败了.我基本上复制了Crockford的Object.create(),除了私有变量.

如果你看看这里接受的答案如何从javascript中继承一个类?,你会看到Object.create是最后一个模式,我认为它更符合Javascript(对象beget对象)的原型性质,而不是模仿经典继承(类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;
};
Run Code Online (Sandbox Code Playgroud)

然后,您可以这样创建对象:

// 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
Run Code Online (Sandbox Code Playgroud)

我创建"from"函数的方式是,当父对象更改其方法时,如果要阻止子实例中的更改,可以指定:

this.public_method = this.parent.public_method;
Run Code Online (Sandbox Code Playgroud)

在子实例中.

另请注意,从nihilo创建的对象不从Object继承(hasOwnProperty等).您必须将其明确指定为.from(Object).

这种模式的好处:

  1. 每个新实例都不会浪费内存
  2. 它坚持真正的原型继承模式
  3. 您可以使用this.parent访问父对象(此.__ proto__是特定于浏览器的)
  4. 私有变量现在存在

我可以想到这种方法的一个主要缺点:'function()'语法可能会让人误以为将函数分配给变量而不是对象.

我的问题是,我还有其他缺点吗?(不要包括原型模式的缺点 - 这是主观的 - 但仅限于我的实现).

use*_*621 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;
};
Run Code Online (Sandbox Code Playgroud)

然后使用

var a = Object.createChild(null, function () { /*...*/ });
var b = Object.createChild(a, function () { /*...*/ });
Run Code Online (Sandbox Code Playgroud)

与上面的结果相同。奖励:您可以省略 constructor 参数,如下所示:

var c = Object.createChild(anything);
Run Code Online (Sandbox Code Playgroud)

其次,我不知道你所说的真正的原型继承是否有任何用处。在现实生活中,我非常确定构造函数是专门针对即将扩展的对象量身定制的 ( a)。因此,你最终会打电话

var x = f.from(a);
var y = f.from(a);
Run Code Online (Sandbox Code Playgroud)

与完全相同fa组合一遍又一遍。是的,与类驱动方法相比,您节省了一些内存字节,但说实话,谁在乎呢?

尽管如此,从理论上讲,整个事情确实是一个好主意。