Javascript继承思想(二)

标签 javascript inheritance prototype

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

如果您在此处查看已接受的答案 How to inherit from a class in javascript? ,你会看到 Object.create 作为最后一个模式,我认为它更符合 Javascript 的原型(prototype)性质(对象产生对象)而不是模拟经典继承(类产生对象)。

如果您查看维基百科关于基于原型(prototype)编程的文章 ( http://en.wikipedia.org/wiki/Prototype-based_programming ),您会明白我的意思。

不过 Object.create() 的缺点是不支持私有(private)成员。这就是我的建议:

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;

在子实例中。

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

这种模式的好处:

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

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

我的问题是,还有其他我遗漏的缺点吗? (不要包括原型(prototype)模式的缺点——这是主观的——但只是我的实现)。

最佳答案

首先,如前所述,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);

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

var x = f.from(a);
var y = f.from(a);

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

不过,整个事情在理论上是一个非常好的想法。

关于Javascript继承思想(二),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3376188/

相关文章:

iphone - Objective-C:继承和动态类型?

javascript - 覆盖 JavaScript 中的函数

javascript - 如何在给定的 map 投影中执行 d3.svg.arc?

javascript - Vue : Append component to element

javascript - 将窗口滚动到 contenteditable block 的当前行

java - JPA 实体的继承

c# - 如何将父转换为子以在 C# 中调用正确的函数

Javascript:重写子类中继承的方法后如何运行父类的构造函数逻辑?

javascript - 原型(prototype): "this"的深层范围以访问实例的范围

javascript - 动态地将名称属性添加到字符串中的标签 - React/JS