जावास्क्रिप्ट में एक वर्ग को परिभाषित करने के लिए किन तकनीकों का उपयोग किया जा सकता है, और उनके व्यापार-नापसंद क्या हैं?


686

मैं बड़े पैमाने पर परियोजनाओं में OOP का उपयोग करना पसंद करता हूं, जैसे मैं अभी काम कर रहा हूं। मुझे जावास्क्रिप्ट में कई कक्षाएं बनाने की आवश्यकता है लेकिन, अगर मुझसे गलती नहीं हुई है, तो उस बारे में जाने के लिए कम से कम कुछ तरीके हैं। वाक्य रचना क्या होगी और इसे इस तरह से क्यों किया जाएगा?

मैं तीसरे पक्ष के पुस्तकालयों का उपयोग करने से बचना चाहता हूं - कम से कम पहले।
अन्य उत्तरों की तलाश में, मुझे लेख ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग विथ जावास्क्रिप्ट, पार्ट I: इनहेरिटेंस - डॉक जावास्क्रिप्ट मिला, जो जावास्क्रिप्ट में ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग पर चर्चा करता है। क्या वंशानुक्रम करने का एक बेहतर तरीका है?



3
व्यक्तिगत रूप से, मुझे फंक्शन बॉडी के अंदर क्लास मेंबर घोषित करना पसंद है। मैं 'फिक्सिंग द दिस' तकनीक का इस्तेमाल बंद करने के लिए करता हूं ताकि वह क्लास की तरह व्यवहार कर सके। मुझे अपने ब्लॉग पर एक विस्तृत उदाहरण मिला है: ncombo.wordpress.com/2012/12/30/…
जॉन

मैंने एक सरल और प्राकृतिक वाक्य रचना के साथ जावास्क्रिप्ट में C ++ OOP की अधिकांश कार्यक्षमता को पोर्ट किया। मेरा जवाब यहां देखें: stackoverflow.com/a/18239463/1115652

जावास्क्रिप्ट में कोई कक्षाएं नहीं हैं। लेकिन अगर आप जेएस में क्लास-एलाइक व्यवहार को अनुकरण करना चाहते हैं, तो आप कर सकते हैं। विवरण देखें: symfony-world.blogspot.com/2013/10/…
ducin

जवाबों:


743

यहां किसी बाहरी लाइब्रेरी का उपयोग किए बिना इसे करने का तरीका दिया गया है:

// Define a class like this
function Person(name, gender){

   // Add object properties like this
   this.name = name;
   this.gender = gender;
}

// Add methods like this.  All Person objects will be able to invoke this
Person.prototype.speak = function(){
    alert("Howdy, my name is" + this.name);
};

// Instantiate new objects with 'new'
var person = new Person("Bob", "M");

// Invoke methods like this
person.speak(); // alerts "Howdy, my name is Bob"

अब असली उत्तर उससे बहुत अधिक जटिल है। उदाहरण के लिए, जावास्क्रिप्ट में कक्षाएं जैसी कोई चीज नहीं है। जावास्क्रिप्ट एक- prototypeआधारित विरासत योजना का उपयोग करता है ।

इसके अलावा, कई लोकप्रिय जावास्क्रिप्ट पुस्तकालय हैं जिनकी जावास्क्रिप्ट में वर्ग-समान कार्यक्षमता को अनुमानित करने की अपनी शैली है। आप कम से कम प्रोटोटाइप और jQuery की जाँच करना चाहते हैं ।

यह निर्णय लेना कि स्टैक ओवरफ्लो पर पवित्र युद्ध शुरू करने का एक सबसे अच्छा तरीका "सर्वश्रेष्ठ" क्या है। यदि आप एक बड़ी जावास्क्रिप्ट-भारी परियोजना को शुरू कर रहे हैं, तो यह निश्चित रूप से एक लोकप्रिय पुस्तकालय सीखने और इसे अपने तरीके से करने के लायक है। मैं एक प्रोटोटाइप आदमी हूं, लेकिन स्टैक ओवरफ्लो jQuery की ओर झुकाव करने लगता है।

जहाँ तक "इसे करने का केवल एक तरीका" है, बाहरी पुस्तकालयों पर किसी भी निर्भरता के बिना, मैंने जिस तरह से लिखा है वह बहुत अधिक है।


48
लेकिन यह एक्स भाषा की तरह काम नहीं करता है, जहां मैंने एक सही तरीका सीखा है कि एक वस्तु जिसका उपयोग ऑब्जेक्ट इंस्टेंसेस बनाने के लिए किया जाता है, उसे काम करना चाहिए :(
एरिक रेपेन

2
Developer.mozilla.org/en-US/docs/Web/JavaScript/… के अनुसार गुणों को प्रोटोटाइप में भी जोड़ा जाना चाहिए ("Person.prototyp.name = '';")
डेवड

1
@DaveD - शायद यह किया है, लेकिन अब और नहीं लगता है ..?
किरेन जॉनस्टोन

6
jQuery वर्ग जैसी कार्यक्षमता बनाने के लिए कोई भी तरीका प्रदान नहीं करता है ??? (इसमें सीएसएस की सभी कक्षाएं हैं) आपको इसे उत्तर के उस भाग से हटा देना चाहिए।
बरगी

7
एकांत से 2015 के एक्मास्क्रिप्ट 6 नए मानक जारी किए गए थे, इसलिए मैं इसे नए तरीके से करने का प्रस्ताव देता हूं (बहुत क्लीनर और आसान) es6-features.org/#ClassDefinition
DevWL

213

जावास्क्रिप्ट में एक वर्ग को परिभाषित करने का सबसे अच्छा तरीका एक वर्ग को परिभाषित नहीं करना है।

गंभीरता से।

ऑब्जेक्ट-ओरिएंटेशन के कई अलग-अलग स्वाद हैं, उनमें से कुछ हैं:

  • वर्ग-आधारित OO (पहली बार स्मालटाक द्वारा पेश किया गया)
  • प्रोटोटाइप-आधारित OO (पहले स्वयं द्वारा प्रस्तुत)
  • मल्टीमिथोड-आधारित OO (पहले कॉमनवेल्स द्वारा पेश किया गया था, मुझे लगता है)
  • विधेय आधारित OO (कोई विचार नहीं)

और शायद दूसरों के बारे में मुझे जानकारी नहीं है।

जावास्क्रिप्ट प्रोटोटाइप-आधारित OO को लागू करता है। प्रोटोटाइप-आधारित OO में, नई ऑब्जेक्ट्स को अन्य ऑब्जेक्ट्स (क्लास टेम्पलेट से तात्कालिक होने के बजाय) और क्लासेस के बजाय ऑब्जेक्ट्स में सीधे रहते हैं। प्रत्यायोजन प्रतिनिधिमंडल के माध्यम से किया जाता है: यदि किसी वस्तु में कोई विधि या संपत्ति नहीं है, तो इसे उसके प्रोटोटाइप (एस) पर देखा जाता है (यानी जिस वस्तु से इसे क्लोन किया गया था), फिर प्रोटोटाइप का प्रोटोटाइप और इसी तरह।

दूसरे शब्दों में: कोई वर्ग नहीं हैं।

जावास्क्रिप्ट वास्तव में उस मॉडल का एक अच्छा ट्विस्ट है: निर्माता। न केवल आप मौजूदा लोगों को कॉपी करके ऑब्जेक्ट बना सकते हैं, आप उन्हें "पतली हवा से बाहर" भी बना सकते हैं, इसलिए बोलने के लिए। यदि आप newकीवर्ड के साथ किसी फ़ंक्शन को कॉल करते हैं , तो वह फ़ंक्शन एक कंस्ट्रक्टर बन जाता है और thisकीवर्ड वर्तमान ऑब्जेक्ट को इंगित नहीं करेगा, बल्कि एक नए बनाए गए "खाली" के बजाय। इसलिए, आप किसी भी तरह से किसी वस्तु को कॉन्फ़िगर कर सकते हैं। इस तरह, जावास्क्रिप्ट निर्माता पारंपरिक वर्ग-आधारित OO में कक्षाओं की भूमिकाओं में से एक पर ले जा सकते हैं: नई वस्तुओं के लिए टेम्पलेट या ब्लूप्रिंट के रूप में सेवारत।

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


"यदि आप नए कीवर्ड के साथ किसी फ़ंक्शन को कॉल करते हैं, तो वह फ़ंक्शन एक कंस्ट्रक्टर बन जाता है और यह कीवर्ड वर्तमान ऑब्जेक्ट को इंगित नहीं करेगा, बल्कि एक नए बनाए गए" खाली "" के बजाय। यदि आप नए कीवर्ड के बिना किसी फ़ंक्शन को कॉल करते हैं, तो यह कॉलिंग संदर्भ को संदर्भित करेगा, डिफ़ॉल्ट रूप से वैश्विक ऑब्जेक्ट (विंडो)। सख्त मोड में, अपरिभाषित डिफ़ॉल्ट है। कॉल, अप्लाई और बाइंडिंग कॉलिंग संदर्भ को पहले पैरामीटर के रूप में लेता है। developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
एलियास हसले

83

ES2015 क्लासेस

ES2015 विनिर्देश में, आप क्लास सिंटैक्स का उपयोग कर सकते हैं जो प्रोटोटाइप सिस्टम पर सिर्फ चीनी है।

class Person {
  constructor(name) {
    this.name = name;
  }
  toString() {
    return `My name is ${ this.name }.`;
  }
}

class Employee extends Person {
  constructor(name, hours) {
    super(name);
    this.hours = hours;
  }
  toString() {
    return `${ super.toString() } I work ${ this.hours } hours.`;
  }
}

लाभ

मुख्य लाभ यह है कि स्थैतिक विश्लेषण उपकरण को इस वाक्यविन्यास को लक्षित करना आसान लगता है। भाषा को एक बहुभाषाविद के रूप में उपयोग करने के लिए वर्ग-आधारित भाषाओं से आने वाले अन्य लोगों के लिए भी आसान है।

चेतावनियां

अपनी वर्तमान सीमाओं से सावधान रहें। निजी गुणों को प्राप्त करने के लिए, किसी को प्रतीक या WeakMaps का उपयोग करना चाहिए । भविष्य के रिलीज में, इन लापता विशेषताओं को शामिल करने के लिए कक्षाओं का सबसे अधिक विस्तार किया जाएगा।

सहयोग

ब्राउज़र समर्थन पल (आईई को छोड़कर लगभग हर किसी के द्वारा समर्थित) पर बहुत अच्छा नहीं है, लेकिन आप की तरह एक transpiler के साथ अब इन सुविधाओं का उपयोग कर सकते हैं कोलाहल

साधन


56

मैं डैनियल एक्स {SUPER: SYSTEM}। मूर का उपयोग करना पसंद करता हूं । यह एक अनुशासन है जो सच्चे उदाहरण चर, विशेषता आधारित विरासत, वर्ग पदानुक्रम और कॉन्फ़िगरेशन विकल्प जैसे लाभ प्रदान करता है। नीचे दिया गया उदाहरण सत्य उदाहरण चर का उपयोग दिखाता है, जो मुझे विश्वास है कि सबसे बड़ा लाभ है। यदि आपको उदाहरण चर की आवश्यकता नहीं है और केवल सार्वजनिक या निजी चर से खुश हैं तो संभवतः सरल प्रणाली हैं।

function Person(I) {
  I = I || {};

  Object.reverseMerge(I, {
    name: "McLovin",
    age: 25,
    homeState: "Hawaii"
  });

  return {
    introduce: function() {
      return "Hi I'm " + I.name + " and I'm " + I.age;
    }
  };
}

var fogel = Person({
  age: "old enough"
});
fogel.introduce(); // "Hi I'm McLovin and I'm old enough"

वाह, यह वास्तव में अपने आप में बहुत उपयोगी नहीं है, लेकिन एक उपवर्ग जोड़ने पर एक नज़र डालें:

function Ninja(I) {
  I = I || {};

  Object.reverseMerge(I, {
    belt: "black"
  });

  // Ninja is a subclass of person
  return Object.extend(Person(I), {
    greetChallenger: function() {
      return "In all my " + I.age + " years as a ninja, I've never met a challenger as worthy as you...";
    }
  });
}

var resig = Ninja({name: "John Resig"});

resig.introduce(); // "Hi I'm John Resig and I'm 25"

एक अन्य लाभ मॉड्यूल और विशेषता आधारित विरासत रखने की क्षमता है।

// The Bindable module
function Bindable() {

  var eventCallbacks = {};

  return {
    bind: function(event, callback) {
      eventCallbacks[event] = eventCallbacks[event] || [];

      eventCallbacks[event].push(callback);
    },

    trigger: function(event) {
      var callbacks = eventCallbacks[event];

      if(callbacks && callbacks.length) {
        var self = this;
        callbacks.forEach(function(callback) {
          callback(self);
        });
      }
    },
  };
}

व्यक्ति वर्ग के एक उदाहरण में बाइंडेबल मॉड्यूल शामिल है।

function Person(I) {
  I = I || {};

  Object.reverseMerge(I, {
    name: "McLovin",
    age: 25,
    homeState: "Hawaii"
  });

  var self = {
    introduce: function() {
      return "Hi I'm " + I.name + " and I'm " + I.age;
    }
  };

  // Including the Bindable module
  Object.extend(self, Bindable());

  return self;
}

var person = Person();
person.bind("eat", function() {
  alert(person.introduce() + " and I'm eating!");
});

person.trigger("eat"); // Blasts the alert!

प्रकटीकरण: मैं डैनियल एक्स मूर हूं और यह मेरी है {SUPER: SYSTEM}। यह जावास्क्रिप्ट में एक वर्ग को परिभाषित करने का सबसे अच्छा तरीका है।


@DanielXMoore "इंस्टेंस चर को एक वर्ग के अलग-अलग उदाहरणों के बीच साझा किया जाता है" वे इंस्टेंस वेरिएबल नहीं हैं, वे स्थिर / वर्ग चर हैं।
JAB

2
@JAB गलत है, स्थिर / वर्ग चर एक वर्ग के सभी उदाहरणों के बीच साझा किए जाते हैं । प्रत्येक उदाहरण के अपने उदाहरण चर होते हैं।
डेनियल एक्स मूर

("उदाहरण चर" शब्द के सामान्य अर्थ का उपयोग करते हुए एक और तरीका रखो, चाहे एक चर हो या न हो, चर की पहुंच के स्तर के लिए एक orthogonal है।)
JAB

2
आपने लगभग
दादान

जावास्क्रिप्ट वस्तुओं का उपयोग करके एक जावास्क्रिप्ट क्लास को परिभाषित करने के लिए एक आसान तरीका: wapgee.com/story/i/203
इलियास करीम

41
var Animal = function(options) {
    var name = options.name;
    var animal = {};

    animal.getName = function() {
        return name;
    };

    var somePrivateMethod = function() {

    };

    return animal;
};

// usage
var cat = Animal({name: 'tiger'});

यह कुछ भी आयात करने के बिना एक प्रयोग करने योग्य वस्तु संरचना का निर्माण करने के लिए एक बहुत ही सुंदर तरीका है। मैं रेसिग की कक्षा प्रणाली का उपयोग कर रहा था, लेकिन मुझे यह बेहतर लग सकता है। धन्यवाद।
बजे टिम स्कोलिक

29
इस दृष्टिकोण के साथ मुद्दा यह है कि हर बार जब आप एक नया पशु उदाहरण बनाते हैं, तो यह फ़ंक्शन को केवल एक बार प्रोटोटाइप के माध्यम से परिभाषित करने के बजाय कार्यों को फिर से परिभाषित करने वाला होता है।
जस्टिन

33

जावास्क्रिप्ट में वस्तुओं को बनाने के तरीके निम्नलिखित हैं, जो मैंने अब तक उपयोग किए हैं

उदाहरण 1:

obj = new Object();
obj.name = 'test';
obj.sayHello = function() {
    console.log('Hello '+ this.name);
}

उदाहरण 2:

obj = {};
obj.name = 'test';
obj.sayHello = function() {
    console.log('Hello '+ this.name);
}
obj.sayHello();

उदाहरण 3:

var obj = function(nameParam) {
    this.name = nameParam;
}
obj.prototype.sayHello = function() {
    console.log('Hello '+ this.name);
}

उदाहरण 4: Object.create () के वास्तविक लाभ। कृपया देखें [यह लिंक]

var Obj = {
    init: function(nameParam) {
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var usrObj = Object.create(Obj);  // <== one level of inheritance

usrObj.init('Bob');
usrObj.sayHello();

उदाहरण 5 (क्रॉकफोर्ड का ऑब्जेक्ट अनुकूलित करें):

Object.build = function(o) {
   var initArgs = Array.prototype.slice.call(arguments,1)
   function F() {
      if((typeof o.init === 'function') && initArgs.length) {
         o.init.apply(this,initArgs)
      }
   }
   F.prototype = o
   return new F()
}
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}}  // For example

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.build(userB, 'Bob');  // Different from your code
bob.sayHello();


ES6 / ES2015 के साथ उत्तर को अद्यतन रखने के लिए

एक वर्ग को इस तरह परिभाषित किया गया है:

class Person {
    constructor(strName, numAge) {
        this.name = strName;
        this.age = numAge;
    }

    toString() {
        return '((Class::Person) named ' + this.name + ' & of age ' + this.age + ')';
    }
}

let objPerson = new Person("Bob",33);
console.log(objPerson.toString());

1
@ जस्टिन: कृपया मुझे बताएं कि क्या मान्य नहीं है?
अमोल एम कुलकर्णी

इन सूचनाओं का अध्ययन करते समय, मैंने इस पर भी ठोकर खाई। ()। उदाहरण के लिए: this.set ('port', 3000)। मेरा अनुमान है, इसका उपयोग ऑब्जेक्ट के लिए पोर्ट प्रॉपर्टी को सेट करने के लिए किया जाता है। यदि हां, तो हम सीधे उपयोग क्यों नहीं करते हैं: {पोर्ट: 3000}। क्या कोई दस्तावेज है जहां मैं अधिक जानकारी प्राप्त कर सकता हूं।
आदित्य

24

मुझे लगता है कि आप डगलस Crockford के पढ़ना चाहिए जावास्क्रिप्ट में मूलरूप विरासत और जावास्क्रिप्ट में शास्त्रीय विरासत

उनके पृष्ठ के उदाहरण:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

प्रभाव? यह आपको और अधिक सुरुचिपूर्ण तरीके से विधियों को जोड़ने की अनुमति देगा:

function Parenizor(value) {
    this.setValue(value);
}

Parenizor.method('setValue', function (value) {
    this.value = value;
    return this;
});

मैं उनके वीडियो भी सुझाता हूं: उन्नत जावास्क्रिप्ट

आप उसके पृष्ठ पर और अधिक वीडियो पा सकते हैं: http://javascript.crockford.com/ जॉन रीजिग पुस्तक में आप डगलस क्रॉकफोर की वेबसाइट से कई उदाहरण पा सकते हैं।


25
यह सिर्फ मैं हूँ? कैसे बिल्ली यह और अधिक सुंदर है? मैं फ़ंक्शन परिभाषाओं को वास्तविक के 'strings'रूप में कई चीजों के नाम से
बुलाऊंगा

4
@ जेएबी, लेकिन प्रतिबिंब अपवाद है, नियम नहीं। उपरोक्त विधि के साथ, आपको अपने सभी तरीकों को स्ट्रिंग के साथ घोषित करना होगा
कर्क वुल्ल

16

क्योंकि मैं YUI / क्रॉकफ़ोर्ड फ़ैक्टरी योजना को स्वीकार नहीं करूँगा और क्योंकि मैं चीज़ों को अपने पास रखना पसंद करता हूँ और यह मेरे लिए उपयुक्त है।

function Person(params)
{
  this.name = params.name || defaultnamevalue;
  this.role = params.role || defaultrolevalue;

  if(typeof(this.speak)=='undefined') //guarantees one time prototyping
  {
    Person.prototype.speak = function() {/* do whatever */};
  }
}

var Robert = new Person({name:'Bob'});

जहां आदर्श रूप से टाइपो परीक्षण पहली विधि प्रोटोटाइप की तरह कुछ पर है


मुझें यह पसंद है। मैं सबसे अधिक बार जेएस के मानक वाक्यविन्यास का उपयोग करता हूं क्योंकि मुझे प्रत्येक ऑब्जेक्ट उदाहरण में फ़ंक्शन को कॉपी करने का विचार पसंद नहीं है। मैं हमेशा आत्म निहित समाधान की सुंदरता को याद किया, और यह बहुत अच्छी तरह से हल करती है।
लुकाज़ कोरज़ीबकी

1
निश्चित नहीं है, लेकिन मुझे समझ में आया कि फंक्शन के प्रोटोटाइप फ़ंक्शन को कार्यक्षेत्र के दायरे में (कुछ हद तक बंद) एक मेमोरी लीक में परिणाम देता है क्योंकि कचरा कलेक्टर उन वर्गों के उदाहरण में नहीं आ सकता है।
सन्न

15

यदि आप सरल के लिए जा रहे हैं, तो आप "नए" कीवर्ड से पूरी तरह से बच सकते हैं और बस कारखाने के तरीकों का उपयोग कर सकते हैं। मुझे यह पसंद है, कभी-कभी, क्योंकि मुझे ऑब्जेक्ट बनाने के लिए JSON का उपयोग करना पसंद है।

function getSomeObj(var1, var2){
  var obj = {
     instancevar1: var1,
     instancevar2: var2,
     someMethod: function(param)
     {  
          //stuff; 
     }
  };
  return obj;
}

var myobj = getSomeObj("var1", "var2");
myobj.someMethod("bla");

मुझे यकीन नहीं है कि बड़ी वस्तुओं के लिए प्रदर्शन हिट है, हालांकि।


Obj.instancevar1 = var1 लाइन आवश्यक नहीं है, क्योंकि आंतरिक ऑब्जेक्ट तक getSomeObj () के मापदंडों का उपयोग होगा।
त्रिकोणीय डिक

वाह। इससे मेरे मस्तिष्क को चोट पहुंचती है लेकिन इसके लिए एक निश्चित लालित्य है। तो "obj.instancevar1 = var1" भाग एक तरह के कंस्ट्रक्टर की शुरुआत है, मुझे लगता है?
करीम

अभी त्रिपिटक की टिप्पणी देखी। समझा। तो, आप बस "Instvar1: var1" जैसा कुछ कर सकते हैं, जहां आंतरिक वस्तु को त्वरित किया जा रहा है।
करीम

वास्तव में ... जब आप किसी वस्तु को परिभाषित करने के लिए {} का उपयोग करते हैं, तो इसकी पहुंच उन चरों पर होती है जो वर्तमान में हैं।
सैम

10
इस दृष्टिकोण के साथ आप विरासत की क्षमता को ढीला कर देते हैं, और चूंकि आप obj.prototype.something का उपयोग नहीं कर रहे हैं, इसलिए आप हर बार जब आप ऑब्जेक्ट का उपयोग कर रहे हैं = अधिक मेमोरी और धीमी गति से कार्यों को परिभाषित कर रहे हैं।
कुछ

12
var Student = (function () {
    function Student(firstname, lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.fullname = firstname + " " + lastname;
    }

    Student.prototype.sayMyName = function () {
        return this.fullname;
    };

    return Student;
}());

var user = new Student("Jane", "User");
var user_fullname = user.sayMyName();

जिस तरह से टाइपस्क्रिप्ट क्लास को कंस्ट्रक्टर के साथ जावास्क्रिप्ट में संकलित करता है।


10

सरल तरीका है:

function Foo(a) {
  var that=this;

  function privateMethod() { .. }

  // public methods
  that.add = function(b) {
    return a + b;
  };
  that.avg = function(b) {
    return that.add(b) / 2; // calling another public method
  };
}

var x = new Foo(10);
alert(x.add(2)); // 12
alert(x.avg(20)); // 15

इसका कारण thatयह है कि thisअगर आप इवेंट हैंडलर के रूप में एक विधि देते हैं, तो यह किसी और चीज के लिए बाध्य हो सकता है, इसलिए आप तात्कालिकता के दौरान मूल्य को बचाते हैं और बाद में इसका उपयोग करते हैं।

संपादित करें: यह निश्चित रूप से सबसे अच्छा तरीका नहीं है, बस एक सरल तरीका है। मुझे अच्छे उत्तरों की प्रतीक्षा है!


1
यह = यह निर्माण यहाँ आवश्यक नहीं है। इसके अलावा, वर्ग फू के प्रत्येक "उदाहरण" के लिए ऐड () और एवीजी () विधियों को कॉपी किया जाएगा, बजाय उनके बीच साझा किए।
त्रिफलक

1
क्या उस मामले में यह आवश्यक (सॉर्ट) है, लेकिन आपके द्वारा प्रदान किया गया साधारण मामला नहीं है।
त्रिपिटक

9

आप संभवतः तह पैटर्न का उपयोग करके एक प्रकार बनाना चाहते हैं:

    // Here is the constructor section.
    var myType = function () {
        var N = {}, // Enclosed (private) members are here.
            X = this; // Exposed (public) members are here.

        (function ENCLOSED_FIELDS() {
            N.toggle = false;
            N.text = '';
        }());

        (function EXPOSED_FIELDS() {
            X.count = 0;
            X.numbers = [1, 2, 3];
        }());

        // The properties below have access to the enclosed fields.
        // Careful with functions exposed within the closure of the
        // constructor, each new instance will have it's own copy.
        (function EXPOSED_PROPERTIES_WITHIN_CONSTRUCTOR() {
            Object.defineProperty(X, 'toggle', {
                get: function () {
                    var before = N.toggle;
                    N.toggle = !N.toggle;
                    return before;
                }
            });

            Object.defineProperty(X, 'text', {
                get: function () {
                    return N.text;
                },
                set: function (value) {
                    N.text = value;
                }
            });
        }());
    };

    // Here is the prototype section.
    (function PROTOTYPE() {
        var P = myType.prototype;

        (function EXPOSED_PROPERTIES_WITHIN_PROTOTYPE() {
            Object.defineProperty(P, 'numberLength', {
                get: function () {
                    return this.numbers.length;
                }
            });
        }());

        (function EXPOSED_METHODS() {
            P.incrementNumbersByCount = function () {
                var i;
                for (i = 0; i < this.numbers.length; i++) {
                    this.numbers[i] += this.count;
                }
            };
            P.tweak = function () {
                if (this.toggle) {
                    this.count++;
                }
                this.text = 'tweaked';
            };
        }());
    }());

वह कोड आपको एक टाइप देगा, जिसे myType कहा जाता है । इसमें टॉगल और टेक्स्ट नामक आंतरिक निजी फ़ील्ड होंगे । इसमें ये उजागर सदस्य भी होंगे: क्षेत्र गिनती और संख्या ; गुण टॉगल , पाठ और संख्या ; तरीके incrementNumbersByCount और tweak

तह पैटर्न पूरी तरह से यहाँ विस्तृत है: जावास्क्रिप्ट तह पैटर्न


3

@ Liammclennan के उत्तर के लिए कोड गोल्फ ।

var Animal = function (args) {
  return {
    name: args.name,

    getName: function () {
      return this.name; // member access
    },

    callGetName: function () {
      return this.getName(); // method call
    }
  };
};

var cat = Animal({ name: 'tiger' });
console.log(cat.callGetName());


2

MooTools (माई ऑब्जेक्ट ओरिएंटेड टूल्स) कक्षाओं के विचार पर केंद्रित है । आप विरासत के साथ विस्तार और कार्यान्वयन भी कर सकते हैं।

जब महारत हासिल होती है, तो यह हास्यास्पद रूप से पुन: प्रयोज्य, शक्तिशाली जावास्क्रिप्ट के लिए बनाता है।


2

इन्हेरिटेंस के साथ ऑब्जेक्ट आधारित कक्षाएं

var baseObject = 
{
     // Replication / Constructor function
     new : function(){
         return Object.create(this);   
     },

    aProperty : null,
    aMethod : function(param){
      alert("Heres your " + param + "!");
    },
}


newObject = baseObject.new();
newObject.aProperty = "Hello";

anotherObject = Object.create(baseObject); 
anotherObject.aProperty = "There";

console.log(newObject.aProperty) // "Hello"
console.log(anotherObject.aProperty) // "There"
console.log(baseObject.aProperty) // null

सरल, मीठा और हो जाता है।


1

एक आधार

function Base(kind) {
    this.kind = kind;
}

एक कक्षा

// Shared var
var _greeting;

(function _init() {
    Class.prototype = new Base();
    Class.prototype.constructor = Class;
    Class.prototype.log = function() { _log.apply(this, arguments); }
    _greeting = "Good afternoon!";
})();

function Class(name, kind) {
    Base.call(this, kind);
    this.name = name;
}

// Shared function
function _log() {
    console.log(_greeting + " Me name is " + this.name + " and I'm a " + this.kind);
}

कार्य

var c = new Class("Joe", "Object");
c.log(); // "Good afternoon! Me name is Joe and I'm a Object"

1

Triptych के उदाहरण के आधार पर, यह और भी सरल हो सकता है:

    // Define a class and instantiate it
    var ThePerson = new function Person(name, gender) {
        // Add class data members
        this.name = name;
        this.gender = gender;
        // Add class methods
        this.hello = function () { alert('Hello, this is ' + this.name); }
    }("Bob", "M"); // this instantiates the 'new' object

    // Use the object
    ThePerson.hello(); // alerts "Hello, this is Bob"

यह केवल एक एकल ऑब्जेक्ट उदाहरण बनाता है, लेकिन यदि आप एक वर्ग में चर और विधियों के लिए नामों का एक गुच्छा संलग्न करना चाहते हैं, तब भी उपयोगी है। आम तौर पर कंस्ट्रक्टर के लिए "बॉब, एम" तर्क नहीं होगा, उदाहरण के लिए यदि सिस्टम अपने डेटा के साथ सिस्टम पर कॉल करेगा, जैसे कि डेटाबेस या नेटवर्क।

मैं अभी भी जेएस के साथ बहुत नया हूं यह देखने के लिए कि यह prototypeचीज का उपयोग क्यों नहीं करता है।


0

जावास्क्रिप्ट ऑब्जेक्ट-ओरिएंटेड है , लेकिन यह अन्य OOP की तुलना में मौलिक रूप से भिन्न है जावा, C # या C ++ जैसी भाषाओं की । इसे इस तरह समझने की कोशिश मत करो। उस पुराने ज्ञान को बाहर फेंक दो और नए सिरे से शुरू करो। जावास्क्रिप्ट को एक अलग सोच की जरूरत है।

मैं एक अच्छा मैनुअल या विषय पर कुछ पाने के लिए सुझाव देता हूं। मैंने खुद एक्सटजे ट्यूटोरियल को मेरे लिए सबसे अच्छा पाया , हालांकि मैंने इसे पढ़ने से पहले या बाद में फ्रेमवर्क का उपयोग नहीं किया है। लेकिन यह जावास्क्रिप्ट दुनिया में क्या है के बारे में एक अच्छी व्याख्या देता है। क्षमा करें, ऐसा लगता है कि सामग्री हटा दी गई है। इसके बजाय आर्काइव.ऑर्ग कॉपी की लिंक यहां दी गई है । आज काम करता है। : पी


2
वस्तु के उन्मुख? मुझे लगा कि यह कार्यात्मक है
पीटर मोर्टेंसन

"एक्सटीजेएस ट्यूटोरियल" लिंक टूट गया है।
पीटर मोर्टेंसन

मुझे लगता है कि यह समझाने के लिए और अधिक व्याख्यात्मक होगा कि जावास्क्रिप्ट में फ़ंक्शन ऑब्जेक्ट हैं, और जावास्क्रिप्ट के ब्रैकेट-स्कोप नियम प्रत्येक फ़ंक्शन ब्लॉक को गुप्त बनाते हैं।
mibbit

-1

//new way using this and new
function Persons(name) {
  this.name = name;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}

var gee=new Persons("gee");
gee.greeting();

var gray=new Persons("gray");
gray.greeting();

//old way
function createPerson(name){
 var obj={};
 obj.name=name;
 obj.greeting = function(){
 console.log("hello I am"+obj.name);
 }; 
  return obj;
}

var gita=createPerson('Gita');
gita.greeting();

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