【问题标题】:Javascript OOP and Inheritance TechniquesJavascript OOP 和继承技术
【发布时间】:2011-08-11 07:23:48
【问题描述】:

我将在秋季参加我的第一堂 OOP 课程(学习 Java),所以我一直在阅读有关它的内容,并通过一些关于语言的介绍来在上学前熟悉自己。我对学习 Java 感到非常兴奋,但我对 JavaScript 感觉更“自在”。我已经用它完成了一些项目,并且正在努力通过在 JS 中使用 OOP 将我的代码提升到下一个更专业的水平(如果你想说的话)。

目前我正在研究拖动脚本,并通过程序编程将其固定下来。由于这个项目在我的记忆中很新鲜,所以我从这个项目开始,开始转向对象。让我在这里绊倒的是拥有一个“拖动”对象的想法。 . .

function Drag() {
    /* Drag code goes here */
} // constructor

我对 OOP 的想法相当了解,但这让我很困惑。在我经历过的所有例子中,对象总是,嗯,对象。它们是动物或汽车,或自行车等。我还没有遇到行为的对象。我只是不确定它是如何工作的。 . .如果您对此有任何建议,我将不胜感激。

现在继承!我还没有必要使用继承,但是这个主题让我对 JavaScript 感兴趣,因为很多人都为此付出了 2 美分。不过,我认为最流行的方式是John Resig'sDouglas Crockford's 继承方式。

我认为它们是非常简洁的解决方法,但出于某种原因,我不太喜欢它们都需要分配。我想我只是觉得他们不应该那样工作。因此,在查看了更多示例和 Crockford 的方法之后,我想出了这个(非常抱歉,如果其他人已经有,我只是没见过):

Object.prototype.extend = function (Obj) {
    'use strict'; // for jslint

    this.prototype = new Obj();
    this.prototype.constructor = this;
    return this;
}

这是一个使用中的例子,我从here偷了例子然后稍微修改了一下:

Object.prototype.inObj = 1;

function A() {
    'use strict';
    this.inA = 2;
}

A.prototype.inAProto = 3;

function B() {
    'use strict';
    this.inB = 4;
}

/*** HERE IT IS ***/
B.extend(A);

B.prototype.inBProto = 5;

var w = new A();
var x = new B();

document.body.innerHTML = x.inObj + ', ' + x.inA + ', ' + x.inAProto + ', ' + x.inB + ', ' + x.inBProto; // 1, 2, 3, 4, 5
document.body.innerHTML += '<br />';
document.body.innerHTML += w instanceof A && w instanceof Object && x instanceof B && x instanceof A && x instanceof Object; // true

对我来说,它在语法上看起来和感觉都很好,我想知道经验丰富的 JS 开发人员会如何看待它。我对其进行了测试,我知道您可以将 B.extend(A) 放在 B 的定义之前,但不能将其放在 B.prototype.inBProto 之后,否则列表将变为 1、2、3、4,未定义,因为在 extend方法,B 的原型正在被重置。我正在努力解决这个问题,但我觉得B.extend(A) 无论如何都应该直接出现在构造函数的定义之后。

大家怎么看这种方式?提前致谢!

编辑:我开发了一个 [笨拙] 解决方法,它基本上采用继承对象原型的所有属性,然后在被新对象擦除干净后将它们重新添加:

Object.prototype.extend = function (Obj) {
    'use strict';
    var proto, p;

    proto = {};
    for (p in this.prototype) {
        if (this.prototype.hasOwnProperty(p)) {
            proto[p] = this.prototype[p];
        }
    }

    this.prototype = new Obj();
    this.prototype.constructor = this;

    for (p in proto) {
        if (proto.hasOwnProperty(p)) {
            this.prototype[p] = proto[p];
        }
    }

    return this;
};

谁知道呢,也许你不会认为这像我一样笨拙,但它确实有效,而且我认为它很酷! :D

【问题讨论】:

  • 强烈建议不要扩充 Object.prototype,因为它可能会破坏(第三方)代码。我目前正在写一本关于 JavaScript 面向对象和继承的入门书。你可能会感兴趣,不过,我还需要几天时间,因为我是在业余时间做的。
  • @Daniel Baulig Aw,开枪。我想你是对的,虽然我不完全确定如何。我不明白为什么它会破坏其他代码。 . .
  • 也同意@Daniel,但如果你想扩展对象,你不妨包括“defineGetter”和“defineSetter " 到对象属性。 :)
  • defineGetterdefineSetter 在较新版本的 JavaScript 中已弃用。新方式是:developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
  • 查看 jOOPL,我创建的一个面向对象的编程基础,它是完全开源的,使用 Apache v2 许可证:joopl.codeplex.com

标签: javascript oop inheritance


【解决方案1】:

我同意丹尼尔的观点,你不应该扩展基本的 JS 核心。

我可以打破的原因是其他人可能也做过同样的事情。但更多的是不改变核心代码的默认行为。

我会使用不同的方法。而不是扩展Object 使其成为一个函数并使用apply

做了一个简单的模型:http://jsfiddle.net/djEw8/

在此处阅读有关申请:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/function/apply

【讨论】:

  • 所以我想它仍然被认为是一个坏主意,即使我将它包装在 if (Object.prototype.extend !== 'function' || !Object.prototype.extend) 这样的东西中?
  • @Zach:在“其他”情况下你会采取什么明智的行动?使用不同的方法名称?如果 that 与其他东西冲突怎么办?到头来还是不值得。
  • @just someone:不需要else情况,如果函数已经存在,它只是没有定义它。
猜你喜欢
  • 2016-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-22
  • 2011-07-08
  • 1970-01-01
  • 1970-01-01
  • 2011-06-26
相关资源
最近更新 更多