[英]JavaScript OOP in NodeJS: how?
我习惯了 Java 中的经典 OOP。
使用 NodeJS 在 JavaScript 中执行 OOP 的最佳实践是什么?
每个类都是一个带有module.export
的文件?
如何创建类?
this.Class = function() {
//constructor?
var privateField = ""
this.publicField = ""
var privateMethod = function() {}
this.publicMethod = function() {}
}
vs.(我什至不确定它是否正确)
this.Class = {
privateField: ""
, privateMethod: function() {}
, return {
publicField: ""
publicMethod: function() {}
}
}
对比
this.Class = function() {}
this.Class.prototype.method = function(){}
...
继承将如何运作?
是否有用于在 NodeJS 中实现 OOP 的特定模块?
我正在寻找一千种不同的方法来创建类似于 OOP 的东西......但我不知道什么是最常用/最实用/最干净的方法。
额外问题:与 MongooseJS 一起使用的建议“OOP 风格”是什么? (可以将 MongooseJS 文档视为一个类和一个用作实例的模型吗?)
编辑
这是JsFiddle 中的一个示例,请提供反馈。
//http://javascriptissexy.com/oop-in-javascript-what-you-need-to-know/
function inheritPrototype(childObject, parentObject) {
var copyOfParent = Object.create(parentObject.prototype)
copyOfParent.constructor = childObject
childObject.prototype = copyOfParent
}
//example
function Canvas (id) {
this.id = id
this.shapes = {} //instead of array?
console.log("Canvas constructor called "+id)
}
Canvas.prototype = {
constructor: Canvas
, getId: function() {
return this.id
}
, getShape: function(shapeId) {
return this.shapes[shapeId]
}
, getShapes: function() {
return this.shapes
}
, addShape: function (shape) {
this.shapes[shape.getId()] = shape
}
, removeShape: function (shapeId) {
var shape = this.shapes[shapeId]
if (shape)
delete this.shapes[shapeId]
return shape
}
}
function Shape(id) {
this.id = id
this.size = { width: 0, height: 0 }
console.log("Shape constructor called "+id)
}
Shape.prototype = {
constructor: Shape
, getId: function() {
return this.id
}
, getSize: function() {
return this.size
}
, setSize: function (size) {
this.size = size
}
}
//inheritance
function Square(id, otherSuff) {
Shape.call(this, id) //same as Shape.prototype.constructor.apply( this, arguments ); ?
this.stuff = otherSuff
console.log("Square constructor called "+id)
}
inheritPrototype(Square, Shape)
Square.prototype.getSize = function() { //override
return this.size.width
}
function ComplexShape(id) {
Shape.call(this, id)
this.frame = null
console.log("ComplexShape constructor called "+id)
}
inheritPrototype(ComplexShape, Shape)
ComplexShape.prototype.getFrame = function() {
return this.frame
}
ComplexShape.prototype.setFrame = function(frame) {
this.frame = frame
}
function Frame(id) {
this.id = id
this.length = 0
}
Frame.prototype = {
constructor: Frame
, getId: function() {
return this.id
}
, getLength: function() {
return this.length
}
, setLength: function (length) {
this.length = length
}
}
/////run
var aCanvas = new Canvas("c1")
var anotherCanvas = new Canvas("c2")
console.log("aCanvas: "+ aCanvas.getId())
var aSquare = new Square("s1", {})
aSquare.setSize({ width: 100, height: 100})
console.log("square overridden size: "+aSquare.getSize())
var aComplexShape = new ComplexShape("supercomplex")
var aFrame = new Frame("f1")
aComplexShape.setFrame(aFrame)
console.log(aComplexShape.getFrame())
aCanvas.addShape(aSquare)
aCanvas.addShape(aComplexShape)
console.log("Shapes in aCanvas: "+Object.keys(aCanvas.getShapes()).length)
anotherCanvas.addShape(aCanvas.removeShape("supercomplex"))
console.log("Shapes in aCanvas: "+Object.keys(aCanvas.getShapes()).length)
console.log("Shapes in anotherCanvas: "+Object.keys(anotherCanvas.getShapes()).length)
console.log(aSquare instanceof Shape)
console.log(aComplexShape instanceof Shape)
这是一个开箱即用的示例。 如果你想要更少的“hacky”,你应该使用继承库等。
那么在文件animal.js中你会写:
var method = Animal.prototype;
function Animal(age) {
this._age = age;
}
method.getAge = function() {
return this._age;
};
module.exports = Animal;
要在其他文件中使用它:
var Animal = require("./animal.js");
var john = new Animal(3);
如果你想要一个“子类”,那么在 mouse.js 中:
var _super = require("./animal.js").prototype,
method = Mouse.prototype = Object.create( _super );
method.constructor = Mouse;
function Mouse() {
_super.constructor.apply( this, arguments );
}
//Pointless override to show super calls
//note that for performance (e.g. inlining the below is impossible)
//you should do
//method.$getAge = _super.getAge;
//and then use this.$getAge() instead of super()
method.getAge = function() {
return _super.getAge.call(this);
};
module.exports = Mouse;
您也可以考虑“方法借用”而不是垂直继承。 你不需要从“类”继承来在你的类上使用它的方法。 例如:
var method = List.prototype;
function List() {
}
method.add = Array.prototype.push;
...
var a = new List();
a.add(3);
console.log(a[0]) //3;
作为 Node.js 社区,确保及时将 JavaScript ECMA-262 规范中的新功能提供给 Node.js 开发人员。
您可以查看JavaScript 类。 JS 类的 MDN 链接在 ECMAScript 6 中引入了 JavaScript 类,此方法提供了在 Javascript 中对 OOP 概念进行建模的更简单方法。
注意:JS 类只能在严格模式下工作。
下面是一些类的骨架,用 Node.js 编写的继承(使用 Node.js 版本v5.0.0 )
类声明:
'use strict';
class Animal{
constructor(name){
this.name = name ;
}
print(){
console.log('Name is :'+ this.name);
}
}
var a1 = new Animal('Dog');
继承:
'use strict';
class Base{
constructor(){
}
// methods definitions go here
}
class Child extends Base{
// methods definitions go here
print(){
}
}
var childObj = new Child();
我建议使用标准util
模块附带的inherits
助手: http : //nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor
在链接页面上有一个如何使用它的示例。
这是互联网上关于面向对象的 JavaScript 的最佳视频:
从头看到尾!!
基本上,Javascript 是一种基于原型的语言,它与 Java、C++、C# 和其他流行朋友中的类有很大不同。 该视频比此处的任何答案都更好地解释了核心概念。
在 ES6(2015 年发布)中,我们得到了一个“class”关键字,它允许我们像使用 Java、C++、C#、Swift 等一样使用 Javascript“类”。
在 Javascript 社区中,很多人认为不应该使用 OOP,因为原型模型不允许在本地进行严格和健壮的 OOP。 但是,我不认为 OOP 是语言问题,而是架构问题。
如果你想在 Javascript/Node 中使用真正强大的 OOP,你可以看看全栈开源框架Danf 。 它为强大的 OOP 代码(类、接口、继承、依赖注入等)提供了所有需要的特性。 它还允许您在服务器(节点)和客户端(浏览器)端使用相同的类。 此外,借助 Npm,您可以编写自己的 danf 模块并与任何人共享。
如果您自己工作,并且想要最接近 OOP 的东西,就像您在 Java、C# 或 C++ 中找到的那样,请参阅 javascript 库 CrxOop。 CrxOop 提供了 Java 开发人员有些熟悉的语法。
请注意,Java 的 OOP 与 Javascript 中的 OOP 不同。 要获得与 Java 相同的行为,请使用 CrxOop 的类,而不是 CrxOop 的结构,并确保所有方法都是虚拟的。 语法的一个例子是,
crx_registerClass("ExampleClass",
{
"VERBOSE": 1,
"public var publicVar": 5,
"private var privateVar": 7,
"public virtual function publicVirtualFunction": function(x)
{
this.publicVar1 = x;
console.log("publicVirtualFunction");
},
"private virtual function privatePureVirtualFunction": 0,
"protected virtual final function protectedVirtualFinalFunction": function()
{
console.log("protectedVirtualFinalFunction");
}
});
crx_registerClass("ExampleSubClass",
{
VERBOSE: 1,
EXTENDS: "ExampleClass",
"public var publicVar": 2,
"private virtual function privatePureVirtualFunction": function(x)
{
this.PARENT.CONSTRUCT(pA);
console.log("ExampleSubClass::privatePureVirtualFunction");
}
});
var gExampleSubClass = crx_new("ExampleSubClass", 4);
console.log(gExampleSubClass.publicVar);
console.log(gExampleSubClass.CAST("ExampleClass").publicVar);
代码是纯javascript,没有转译。 该示例取自官方文档中的多个示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.