簡體   English   中英

NodeJS 中的 JavaScript OOP:如何?

[英]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 權威指南

從頭看到尾!!

基本上,Javascript 是一種基於原型的語言,它與 Java、C++、C# 和其他流行朋友中的類有很大不同。 該視頻比此處的任何答案都更好地解釋了核心概念。

在 ES6(2015 年發布)中,我們得到了一個“class”關鍵字,它允許我們像使用 Java、C++、C#、Swift 等一樣使用 Javascript“類”。

顯示如何編寫和實例化 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM