在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最好。 请注意,一些性能提升是因为它避免使用new
或object.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'