使用Node.js进行JavaScript的面向对象编程

17

我正在编写一个小游戏尝试使用Javascript,我想实现在http://www.crockford.com/javascript/inheritance.html上找到的东西,它类似于:

ZParenizor.method('toString', function () {
    if (this.getValue()) {
        return this.uber('toString');
    }
    return "-0-";
});

我找不到任何关于用于实现此类开发的库的参考。有什么想法吗?否则,我正在寻找一个可以帮助我的面向对象编程(OOP)开发的好库。

谢谢

编辑:

我正在寻找一个适用于Node.js的OOP解决方案/库。请注意,我对Node.js还很新。


2
Crockford 是一个很好的 JavaScript 参考人。你已经开始得很不错了。 - vol7ron
1
只是为了更具体一些,我正在使用Node.js,并且不需要整个库提供DOM操作、效果、ajax等功能... - Cybrix
还可以查看这个答案,了解如何使用JS进行对象构建/继承。干杯! - obimod
7个回答

76

两个月后

也许你确实需要一个库,ES5代码非常冗长,所以我创建了pd

原始回答

我正在寻找Node.js的面向对象解决方案/库。

不需要使用库。你有ES5

JavaScript没有经典的面向对象编程(OOP),它具有原型式OOP。

这意味着你只有对象。你可以做的唯一事情就是扩展、操作和克隆它们。

操作

var o = {};
o.foo = "bar";

扩展

var o = someObject;
Object.defineProperties(o, {
  "foo": { value: "foo" },
  "bar": { value: "bar" }
  "method": { value: function () { } }
}

克隆

var o = someObject;
var p = Object.create(o);

克隆和扩展

var o = someObject;
var p = Object.create(o, {
  "foo": { value: "foo" },
  "bar": { value: "bar" }
  "method": { value: function () { } }
}

了解如何使用Object.createObject.definePropertyObject.defineProperties非常重要。

克隆操作并不是真正的克隆。它是根据一个蓝图创建一个新对象。蓝图是一个对象,它被放置在 [[Prototype]] 中。 [[Prototype]] 存在于 .__proto__ 属性中,我将在演示中使用它。

var o = {};
var p = Object.create(o);
p.__proto__ === o; // true
var q =  Object.create(p);
q.__proto__.__proto__ === o;
var r = Object.create(q);
r.__proto__.__proto__.__proto__ === o;

声明:.__proto__已经被弃用,请勿在代码中使用。但是它在调试和检查健康时有其用途。

这里的关键点是,在r中从o访问属性需要向原型链上走3层,这会导致性能问题。为了解决这个问题,你应该克隆特定的蓝图而不是随意地克隆对象(每个对象应该有一个蓝图)。

// Parent blueprint
var Parent = (function _Parent() {
  // create blank object
  var self = Object.create({});

  // object logic

  return self;
}());

// factory function
var createParent = function _createParent(foo) {
  // create a object with a Parent prototype
  return Object.create(Parent, {
    foo: { value: foo }
  });
}

var Child = (function _Child() {
  var self = Object.create(Parent);

  // other stuff

  return self;
}());

var createChild = function _createChild(bar) {
  return Object.create(Child, {
    bar: { value: bar }
  })
};

这里是我正在处理的一些代码片段,你可以将其用作示例:

var Sketchpad = (function _SketchPad() {
    var self = Object.create({});

    var mousemove = function _mousemove(e) {
        this.drawLine(e);
    };

    self._init = function _init() {
        this.$elem.bind({
            "mousemove": mousemove.bind(this),
        });
        this.pens = {};

        $("#clear").bind("click", this.clear.bind(this));
        $("#undo").bind("click", (function _undoPath() {
            this.pen.undo();
        }).bind(this));

        return this;
    };

    self.clear = function() {
        this.paper.clear();    
    };

    return self;    
}());

createSketch = function _createSketchPad(id, w, h) {
    var paper = Raphael(id, w, h);
    var pen = createPen(paper);
    var o = Object.create(Sketchpad, {
        paper: { value: paper },
        $elem: { value: $("#" + id) },
        pen: { 
            get: function() { return pen; },
            set: function(v) { pen = v; }
        }
    });

    return o._init();
};

5
这就是为什么我加入了 Stack Overflow。+1 - Thomas Shields

8

我非常喜欢这个教程链接。我确实正在寻找类似于Mootools的面向对象方面的东西。事实上,我正在尝试使用Node.js,我怀疑我不需要整个库(Mootools)。 - Cybrix
有客户端框架。MooTools 在服务器上是无用的。 - Raynos
很遗憾,在问题被编辑为指定服务器端JS之后,我收到了一个踩票... :( - Colin
是的,话说有一个Node.js版本:https://github.com/vsviridov/mootools-node。 - Luis

5

您可能也对GNU Ease.js感兴趣。如果您对该库本身不感兴趣,那么它的手册详细介绍了实现细节。

您还可以查看作者有关ECMAScript中经典面向对象编程的论文


3

2
在你所引用的文章中,他只是举了一个例子来展示JavaScript继承的可能性。他没有使用框架,而是向你展示如何扩展自己编写的类。
JavaScript的框架包括Backbone.js(MVC)和MooTools(OOP)。

哦,我希望他能给出一个完整的例子。看起来他(Crockford)用他的例子“做”起来更容易理解。 - Cybrix
MooTools是一个客户端框架。我避免在服务器上使用它。Backbone是一个很棒的服务器端MVC封装。 - Raynos
当这条评论发布时,Cybrix并不清楚他想要它在服务器上。 - helloandre

1
如果你想在Javascript/Node中进行真正的强大的面向对象编程,可以看一下全栈开源框架Danf
它允许你在服务器(node)和客户端(浏览器)两侧使用面向对象编程(以及相同的类)。同时,它还提供了一个不错的依赖注入机制(如果你来自PHP社区,则与Symfony2的机制类似)。

1

extjs支持使用Ext.defineExt.extend(以及Ext.ns)进行面向对象编程。请参见Sencha.com上的this example

Ext.extend是旧的方法,但有时仍然有用。您可以像这样操作:

Ext.ns('myApp.myPackage');  // create a namespace 
(function() { // this adds it to the namespace

var MyClass = Ext.extend(BaseClass, {
    property: 1,

    constructor: function(config) {
        Ext.apply(this, config);
    },

    method: function(a, b) { 
        this.property = a + b;
    }
});

myApp.myPackage.MyClass = MyClass;

}) ()

使用Ext 4+中的Ext.define,您可以执行以下操作:

Ext.define('myApp.myPackage.MyClass', // don't need to define the namespace first
    extend: 'BaseClass' // notice the base class is referenced by a string,
    requires: 'AnotherClass',
    mixins: { mixin : 'MixinPackage' },

    property: 1,

    constructor: function(config) {
        //...
    }

   method: function(a, b) {
        this.property = a + b;
    }
});

请注意,您也可以使用传统的JavaScript中的面向对象编程,并使用'new'和function.prototype。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接