NodeJS में जावास्क्रिप्ट OOP: कैसे?


118

मैं शास्त्रीय OOP के रूप में जावा में उपयोग किया जाता हूं।

NodeJS का उपयोग करके जावास्क्रिप्ट में OOP करने के लिए सर्वोत्तम अभ्यास क्या हैं?

प्रत्येक कक्षा एक फ़ाइल है module.export?

कैसे बनाएं क्लासेस?

this.Class = function() {
    //constructor?
    var privateField = ""
    this.publicField = ""
    var privateMethod = function() {}
    this.publicMethod = function() {} 
}

बनाम (मुझे भी यकीन नहीं है कि यह सही है)

this.Class = {
    privateField: ""
    , privateMethod: function() {}

    , return {
        publicField: ""
        publicMethod: function() {}
    }
}

बनाम

this.Class = function() {}

this.Class.prototype.method = function(){}

...

वंशानुक्रम कैसे काम करेगा?

क्या NodeJS में OOP लागू करने के लिए विशिष्ट मॉड्यूल हैं?

मैं OOP जैसी चीजों को बनाने के लिए एक हजार अलग-अलग तरीके ढूंढ रहा हूं .. लेकिन मुझे कोई सुराग नहीं है कि सबसे ज्यादा इस्तेमाल किया जाने वाला / व्यावहारिक / साफ तरीका क्या है।

बोनस प्रश्न : MongooseJS के साथ उपयोग करने के लिए सुझाए गए "OOP शैली" क्या है? (क्या एक MongoJJS दस्तावेज़ को एक वर्ग और एक उदाहरण के रूप में उपयोग किए जाने वाले मॉडल के रूप में देखा जा सकता है?)

संपादित करें

यहाँ 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)

12
वहाँ नोड में वास्तव में OO JS के बारे में कुछ खास नहीं है। सिर्फ OO JS है। आपका प्रश्न जावा ओओपी तकनीकों को जेएस में अनुवाद करने के बारे में है , जो सिर्फ सही नहीं है । मुझे लगता है कि जेएस के प्रोटोटाइप-आधारित मॉडल कैसे काम करते हैं, यह सीखने में आपने उसी समय / ऊर्जा को बेहतर तरीके से व्यतीत किया और आप इसे अपने लाभ के लिए कैसे उपयोग कर सकते हैं
इलायस वान ओटेगेम

1
इसके अलावा, आपके पास जावास्क्रिप्ट में कक्षाएं नहीं हैं। आप फ़ंक्शंस के साथ क्लास जैसा व्यवहार बना सकते हैं, लेकिन यह आम तौर पर एक अच्छा विचार नहीं है।
m_vdbeek

1
@AwakeZoldiek आपके लिए इसका क्या मतलब है "मूल विशेषता" नहीं है?
एस्लिजा

4
@fusio सामान्य रूप में प्रोटोटाइप विरासत के साथ, ऑब्जेक्ट्स / इंस्टेंसेस अन्य ऑब्जेक्ट्स / इंस्टेंसेस से इनहेरिट करते हैं। इसलिए, कक्षाओं का उपयोग नहीं किया जाता है क्योंकि आप अमूर्त परिभाषाओं के साथ काम नहीं कर रहे हैं। तो, विरासत एक prototypeश्रृंखला के माध्यम से किया जाता है । और, नहीं, वस्तु " निजी " सदस्यों का समर्थन नहीं करती है । केवल क्लोजर ही पेशकश कर सकते हैं, हालांकि Node.js में मॉड्यूल / स्क्रिप्ट को क्लोजर के रूप में लागू किया गया है।
जोनाथन लोनोस्की

1
@Esailija मैं वास्तव में बंद करने का सुझाव देने का मतलब यह नहीं था कि निजी सदस्य बना सकता हूं। केवल यह सुझाव दे रहा था कि जावास्क्रिप्ट में बंद और संलग्न चर उतने ही करीब हो सकते हैं जितने कि आप जावास्क्रिप्ट में प्राप्त कर सकते हैं । लेकिन, दूसरे भाग के लिए: केवल " कार्यान्वयन " मैंने उल्लेख किया नोड मॉड्यूल, जिसका मूल्यांकन एक क्लोजर के भीतर किया जाता है जहां कुछ ग्लोबल्स प्रत्येक स्क्रिप्ट के लिए अद्वितीय परिभाषित किए जाते हैं।
जोनाथन लोनोवस्की

जवाबों:


116

यह एक उदाहरण है जो बॉक्स से बाहर काम करता है। यदि आप कम "हैकी" चाहते हैं, तो आपको विरासत पुस्तकालय या इस तरह का उपयोग करना चाहिए।

एक जानवर में अच्छी तरह से। जेएस आप लिखेंगे:

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;

क्या उपयोग करने Animal.prototype.getAge= function(){}और बस this.getAge = function(){}अंदर जोड़ने के बीच अंतर है function Animal() {}? उप-वर्ग थोड़ा सा हैक्य लगता है .. "वंशानुक्रम" लाइब्रेरी के साथ आपका मतलब कुछ ऐसा है जैसे inherits@badsyntax द्वारा सुझाया गया है?
फुसिओ

4
@fusio हां, आप कुछ ऐसा कर सकते हैं inherits(Mouse, Animal);जो विरासत में मिली सफाई को थोड़ा बढ़ा देता है। अंतर यह है कि आप एक फ़ंक्शन साझा करने के बजाय प्रत्येक तात्कालिक वस्तु के लिए नई फ़ंक्शन पहचान बना रहे हैं। यदि आपके पास 10 चूहे हैं, तो आपने 10 फ़ंक्शन आइडेंटिटी बनाई हैं (यह केवल इसलिए है क्योंकि माउस में एक विधि है, यदि इसमें 10 विधियाँ हैं, तो 10 चूहे 100 फ़ंक्शन पहचान बनाएंगे, आपका सर्वर जीसी: पी पर अपने अधिकांश सीपीयू को जल्दी बर्बाद कर देगा) , भले ही आप उन्हें किसी भी चीज के लिए इस्तेमाल नहीं करेंगे। वर्तमान में इसे दूर करने के लिए भाषा में पर्याप्त अभिव्यंजक शक्ति नहीं है।
एस्लेइजा

ओह। धन्यवाद :) यह काफी सरल लगता है, मुझे यह भी मिला कि Details_of_the_Object_Model जहां वे जावा के साथ JS की तुलना करते हैं। फिर भी, विरासत में वे बस करते हैं: Mouse.prototype = new Animal().. यह आपके उदाहरण के साथ कैसे तुलना करता है? (उदा। क्या है Object.create()?)
fusio

@fusio Object.create कंस्ट्रक्टर को इनवाइट नहीं करता है ... अगर कंस्ट्रक्टर के साइड इफेक्ट्स या ऐसे हैं (यह जावा के विपरीत एक सामान्य फंक्शन कुछ भी कर सकता है), तो इनहेरिटेंस चेन सेट करते समय इसे इन्वोक करना अवांछनीय है।
एस्लेइजा

3
मैं अभी भी किसी को बनाए रखने के लिए जो जावास्क्रिप्ट का उपयोग करना शुरू कर रहा हूं, इस तरह से एक समाधान को हैक करना एक अच्छा समाधान नहीं है। वहाँ बहुत सारे quirks और नुकसान हैं जो यह डीबग करना आसान नहीं है कि यह सलाह नहीं दी जानी चाहिए।
m_vdbeek

43

जैसा कि Node.js समुदाय सुनिश्चित करता है कि जावास्क्रिप्ट ECMA-262 विनिर्देश से नई सुविधाओं को समयबद्ध तरीके से Node.js डेवलपर्स में लाया जाता है।

आप जावास्क्रिप्ट कक्षाओं पर एक नज़र डाल सकते हैं । JS कक्षाओं में MDN लिंक ECMAScript 6 में जावास्क्रिप्ट कक्षाएं शुरू की गई हैं, यह विधि जावास्क्रिप्ट में OOP अवधारणाओं को मॉडल करने का आसान तरीका प्रदान करती है।

नोट : जेएस कक्षाएं केवल सख्त मोड में काम करेंगी ।

नीचे वर्ग के कुछ कंकाल हैं, जो विरासत में लिखे गए हैं 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();

14

मैं inheritsमानक utilमॉड्यूल के साथ आने वाले सहायक का उपयोग करने का सुझाव देता हूं : http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor

लिंक किए गए पृष्ठ पर इसका उपयोग करने का एक उदाहरण है।


कोर NodeJS पर्यावरण के संबंध में यह सबसे उपयोगी उत्तर है।
फिलजेन

1
लगता है अब पदावनत हो गए। उत्तर लिंक से: नोट: use.inherits () का उपयोग हतोत्साहित किया जाता है। कृपया भाषा स्तर विरासत समर्थन पाने के लिए ES6 वर्ग का उपयोग करें और कीवर्ड बढ़ाएँ। यह भी ध्यान दें कि दो शैलियाँ शब्दार्थ रूप से असंगत हैं।
फ्रॉस्टी जेड

11

यह इंटरनेट पर ऑब्जेक्ट-ओरिएंटेड जावास्क्रिप्ट के बारे में सबसे अच्छा वीडियो है:

ऑब्जेक्ट-ओरिएंटेड जावास्क्रिप्ट के लिए निश्चित गाइड

शुरू से अंत तक देखें !!

मूल रूप से, जावास्क्रिप्ट एक प्रोटोटाइप-आधारित भाषा है जो जावा, C ++, C #, और अन्य लोकप्रिय दोस्तों की कक्षाओं से काफी अलग है। वीडियो यहाँ किसी भी उत्तर की तुलना में बेहतर कोर अवधारणाओं की व्याख्या करता है।

ईएस 6 (जारी 2015) के साथ हमें एक "वर्ग" कीवर्ड मिला, जो हमें जावास्क्रिप्ट "कक्षाओं" का उपयोग करने की अनुमति देता है जैसे हम जावा, सी ++, सी #, स्विफ्ट, आदि के साथ करेंगे।

एक जावास्क्रिप्ट कक्षा / उपवर्ग को लिखने और त्वरित करने के तरीके दिखाने वाले वीडियो से स्क्रीनशॉट: यहां छवि विवरण दर्ज करें


मैं सराहना करता हूं कि आपने ES6 के लिए उत्तर दिया है। धन्यवाद! दुर्भाग्य से, मेरे पास 27 मिनट का वीडियो देखने के लिए डेटा नहीं है। मैं लिखित मार्गदर्शन के लिए अपनी खोज जारी रखूंगा।
टिमरोहेर

वीडियो के लिए धन्यवाद। मैंने मुझे जावास्क्रिप्ट के बारे में बहुत सारे प्रश्न स्पष्ट करने में मदद की।
किशोर देवराज

4

जावास्क्रिप्ट समुदाय में, बहुत से लोग तर्क देते हैं कि OOP का उपयोग नहीं किया जाना चाहिए क्योंकि प्रोटोटाइप मॉडल मूल रूप से एक सख्त और मजबूत OOP करने की अनुमति नहीं देता है। हालाँकि, मुझे नहीं लगता कि OOP एक नुकसान की बात है, बल्कि वास्तुकला का मामला है।

यदि आप जावास्क्रिप्ट / नोड में एक वास्तविक मजबूत ओओपी का उपयोग करना चाहते हैं, तो आप पूर्ण-स्टैक ओपन सोर्स फ्रेमवर्क आरएफ पर एक नज़र डाल सकते हैं । यह एक मजबूत ओओपी कोड (कक्षाएं, इंटरफेस, विरासत, निर्भरता-इंजेक्शन, ...) के लिए सभी आवश्यक सुविधाएँ प्रदान करता है। यह आपको सर्वर (नोड) और क्लाइंट (ब्राउज़र) दोनों पक्षों पर समान कक्षाओं का उपयोग करने की अनुमति देता है। इसके अलावा, आप अपने स्वयं के danf मॉड्यूल को कोड कर सकते हैं और Npm के लिए किसी के भी साथ साझा कर सकते हैं।


-1

यदि आप अपने दम पर काम कर रहे हैं, और आप ओओपी के लिए निकटतम चीज़ चाहते हैं, जैसा कि आप जावा या सी # या सी ++ में पाएंगे, तो जावास्क्रिप्ट लाइब्रेरी, क्रैक्सऑप देखें। CrxOop जावा डेवलपर्स के लिए कुछ हद तक सिंटैक्स प्रदान करता है।

बस सावधान रहें, जावा का ओओपी वैसा नहीं है जैसा कि जावास्क्रिप्ट में पाया जाता है। जावा के समान व्यवहार प्राप्त करने के लिए, 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);

कोड शुद्ध जावास्क्रिप्ट है, कोई ट्रांसप्लिंग नहीं। उदाहरण आधिकारिक प्रलेखन से कई उदाहरणों से लिया गया है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.