在NodeJS中创build对象的build议方式是什么?

我正在构build一个request模块的组合,但是我不确定有什么关于构buildJS for Node的对象的最佳实践。

选项1:

 function RequestComposite(request) { return { get: function (url) { return request.get(url); } } } var comp = RequestComposite(request); 
  • 注意:我知道我应该以asynchronous方式调用一个CB,但为了便于解释,我将它返回…

选项2:

 function RequestComposite(request) { this.request = request; } RequestComposite.prototype.get = function (url) { return this.request.get(url); }; var comp = new RequestComposite(request); 

备选案文3:

 var RequestComposite = { init: function (request) { this.request = request; }, get: function (url) { return request.get(url); } } var comp = Object.create(RequestComposite).init(request); 

我试图find我的方式,但是我更加困惑如何使用对象…

如果我想使用浏览器的对象,答案会不同吗?

谢谢。

最有效的方法如下:

  • 只在构造函数中设置属性。

  • 在构造函数的.prototype属性中设置方法。 为什么? 因为这可以防止每次创build对象时重写每个方法。 这样,您可以为每个创build的对象回收相同的原型。 有效的记忆和时间。

  • 不要使用封闭的私有财产。 为什么?:这很慢,并且阻止你在inheritance链中使用这个对象(伪私有variables不属于对象,它们只是可访问的)。 用一个下划线来表示它是一个不应该从外部访问的私有属性。

  • 使用new而不是Object.create 。 它更快,并在最后Object.create使用new的引擎盖。

换句话说,像这样的东西:

 var Person = function (name) { this._name = name; }; Person.prototype.sayHello = function () { alert('My name is: ' + this._name); }; var john = new Person('John'); john.sayHello(); 

编辑

一些额外的信息:

  • Object.create vs新 。 基准在这里 。 虽然问题是node.js,我认为同样的行为是可以预料的。 (欢迎任何更正)

  • 模拟私有财产的闭包 :你可以在这个问题上阅读。 。 私钥/闭包属性不属于对象这一点是一个编程事实:它们可以被对象方法访问,但不属于对象。 当使用inheritance时,这是一个大混乱。 此外,只有在构造函数中声明的方法才能访问闭包。 原型中定义的方法没有。

  • 在构造函数或原型属性中定义方法 :阅读这个问题 ,并看看这个基准

编辑15/04/2016

三年前我在这里提出的观点仍然是从performance的angular度来看,但我对于“推荐方式”的看法也有一些变化。 工厂职能通常是一个很好的select,这将是OP的第一个方法。 只是一个例子:

 function Person(name) { return { sayHello: function () { alert('My name is: ' + name); } }; } 

然后只是做:

 var p = Person('John'); 

在这种情况下,您可以交换灵活性(没有new耦合,易于与其他“混合”组合)和简单(没有this混乱,简单的对象实例化)的速度和记忆。 一般来说,它们是完全有效的。 如果您有性能问题,并且由于这种创build对象的方式,请还原为其他方法。 Object.create方法也很好,在new和工厂函数的中间下降了(注意:新的class语法是new + prototype语法糖)

总结:我推荐的方法是从创build对象(工厂函数)的最简单和最简单的方法开始,然后在遇到性能问题(在绝大多数情况下永远不会)的情况下使用其他方法。

在JS中创build“类”和“对象”有很多种方法。 我更喜欢这种方式:

 var MyObject = function(args) { // Private var help = "/php/index.php?method=getHelp"; var schedule = "/php/index.php?method=getSchedules"; var ajax = function(url, callback, type) { //.... } // Public this.property = 0; this.getInfo = function() { // ... } // Constructor function(data) { this.property = data; }(args); }; var o = new MyObject(); 

注意:如果您对OOP语法更熟悉,也可以使用仅基于原型方法的语法糖类。

性能比较4种创build对象的方法 – 使用构造函数 (Chrome 61 – https://jsperf.com/create-object-ways

选项A:使用return (最快3倍)

选项B:使用{key:value} (1.5x)

选项C:使用prototype (1x)< – Base

选项D:使用class (1.02x)

选项A接缝performance最好。 请注意,一些性能提升是因为它避免使用newobject.create 。 所以只是为了得到一个公平的testing,这里是另一个testing之间的方法只有对象没有构造函数和属性。


性能比较4种创build方法对象的方法 (Chrome 61 – https://jsperf.com/create-static-object-ways

选项A:使用return (3.2x)

选项B:使用{key:value} (最快3.3倍)

选项C:使用prototype (1.8倍)

选项D:使用class (1.9x)

期权B稍微超过期权A. object.create引起的瓶颈也是new


最佳实践

选项A (使用return )在两种情况下都performance最佳。 如果你有很多方法和属性,这个方法可能会变得杂乱无章。

我更喜欢使用选项A在另一个对象中使用选项B分割构造函数和属性。 这种方法确实需要在参数中发送一个额外的instance引用,但是如果你有多个使用相同属性和构造函数的对象(也可以实现一些OOPinheritance),那么这个方法会很有用。

例:

 // Constructor & Properties Object (Using option A) var UserData = function(request){ // Constructor if ( request.name ) var name = request.name; else var name = 'Not Available'; if ( request.age ) var age = request.age; else var age = null; // Return properties return { userName: name, userAge: age }; }; // Object methods (Using Option B) var Adults = { printName: function(instance){ // Read propery example console.log( 'Mr. ' + instance.userName ); }, changeName: function(instance, newName){ // Write property example instance.userName = newName; }, foo: function(){ console.log( 'foo' ); } }; // Object methods (Using Option B) var Children = { printName: function(instance){ console.log( 'Master ' + instance.userName ); }, bar: function(){ console.log( 'bar' ); } } // Initialize var userData = UserData ( {name: 'Doe', age: 40} ); // Call methods Adults.printName(userData); // Output 'Mr. Doe' Children.printName(userData); // Output 'Master Doe' Adults.foo(); // Output 'foo' Children.bar(); // Output 'bar' Adults.changeName(userData, 'John'); Adults.printName(userData); // Output 'Mr. John'