काइल सिम्पसन का ओलो पैटर्न बनाम प्रोटोटाइप डिजाइन पैटर्न


109

क्या काइल सिम्पसन का "OLOO (ऑब्जेक्ट्स को अन्य ऑब्जेक्ट्स से लिंक करना) पैटर्न" प्रोटोटाइप डिजाइन पैटर्न से किसी भी तरह से अलग है? इसे किसी ऐसी चीज द्वारा गढ़ने के अलावा जो विशेष रूप से "लिंकिंग" (प्रोटोटाइप के व्यवहार) को इंगित करता है और स्पष्ट करता है कि यहां (कक्षाओं का एक व्यवहार) "नकल" नहीं हो रहा है, वास्तव में उसका पैटर्न क्या बताता है?

यहां उनकी पुस्तक "का यू नॉट जेएस: दिस एंड ऑब्जेक्ट प्रोटोटाइप" से काइल के पैटर्न का एक उदाहरण है :

var Foo = {
    init: function(who) {
        this.me = who;
    },
    identify: function() {
        return "I am " + this.me;
    }
};

var Bar = Object.create(Foo);

Bar.speak = function() {
    alert("Hello, " + this.identify() + ".");
};

var b1 = Object.create(Bar);
b1.init("b1");
var b2 = Object.create(Bar);
b2.init("b2");

b1.speak(); // alerts: "Hello, I am b1."
b2.speak(); // alerts: "Hello, I am b2."

2
क्या आप कम से कम उस पैटर्न के वर्णन से लिंक कर सकते हैं, जिसके बारे में आप पूछ रहे हैं। इससे भी बेहतर होगा कि आप अपने प्रश्न में इसका एक कोड उदाहरण दिखाएँ।
jfriend00

4
स्टेफीवरफ्लो पर कभी-कभी गेटिफाई होता है। मैंने उसे यह सवाल ट्वीट किया है :)
Pointy

जवाबों:


155

वास्तव में उसका पैटर्न क्या है?

ओएलओओ लिंक को प्राप्त करने के लिए अन्य (आईएमओ भ्रामक) शब्दार्थ पर परत की आवश्यकता के बिना, प्रोटोटाइप श्रृंखला को गले लगाता है।

तो, इन दो स्निपेट्स का एक ही परिणाम है, लेकिन वहां अलग तरीके से प्राप्त करें।

कंस्ट्रक्टर फॉर्म:

function Foo() {}
Foo.prototype.y = 11;

function Bar() {}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.z = 31;

var x = new Bar();
x.y + x.z;  // 42

OLOO फॉर्म:

var FooObj = { y: 11 };

var BarObj = Object.create(FooObj);
BarObj.z = 31;

var x = Object.create(BarObj);
x.y + x.z;  // 42

दोनों स्निपेट्स में, एक xऑब्जेक्ट [[Prototype]]को किसी ऑब्जेक्ट ( Bar.prototypeया BarObj) से जोड़ा जाता है, जो बदले में तीसरे ऑब्जेक्ट ( Foo.prototypeया FooObj) से जुड़ा होता है ।

स्निपेट्स के बीच रिश्ते और प्रतिनिधिमंडल समान हैं। स्निपेट्स के बीच मेमोरी का उपयोग समान है। कई "बच्चों" बनाने की क्षमता (उर्फ, कई वस्तुओं की तरह x1के माध्यम से x1000, आदि) के टुकड़े के बीच समान है। स्निपेट्स के बीच प्रतिनिधिमंडल ( x.yऔर x.z) का प्रदर्शन समान है। ऑब्जेक्ट निर्माण प्रदर्शन है OLOO साथ धीमी है, लेकिन विवेक की जाँच है कि पता चलता है कि धीमे प्रदर्शन वास्तव में कोई मुद्दा नहीं है।

मुझे लगता है कि ओएलओ की पेशकश का तर्क है कि यह बहुत आसान है कि वस्तुओं को व्यक्त करें और सीधे उन्हें लिंक करें, उन्हें अप्रत्यक्ष रूप से निर्माणकर्ता / newतंत्र के माध्यम से लिंक करें । उत्तरार्द्ध वर्गों के बारे में होने का दिखावा करता है, लेकिन वास्तव में प्रतिनिधिमंडल को व्यक्त करने के लिए सिर्फ एक भयानक वाक्यविन्यास है ( साइड नोट: तो ऐसा ही 6 classसिंटैक्स है!)।

ओएलओयू सिर्फ मध्य-पुरुष को काट रहा है।

यहाँ एक और तुलना है classबनाम ओलो।


2
मुझे आपका उत्तर वास्तव में दिलचस्प लगा और आपकी पुस्तकों में ओएलओओ का विचार आया, मैं इस प्रश्न पर आपकी प्रतिक्रिया चाहूंगा: stackoverflow.com/questions/40395762/ विशेष रूप से यदि आप इस कार्यान्वयन को सही पाते हैं और एक्सेस से संबंधित समाधान कैसे करते हैं निजी सदस्य। अग्रिम में अपने समय के लिए धन्यवाद और अपनी नवीनतम पुस्तक के लिए बधाई।
जिब्बो

लेकिन Object.create(...)की तुलना में कई गुना धीमा है newjsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/…
पियर

3
@ प्रदर्शन वास्तव में समस्या का इतना हिस्सा नहीं है। पवित्रता के बारे में टूटी हुई ब्लॉग पोस्ट लिंक को ठीक किया गया, जो वस्तु निर्माण के प्रदर्शन की जाँच करता है, जो बताता है कि इस बारे में ठीक से कैसे सोचा जाए।
काइल सिम्पसन

2
और jQuery डोम एपीआई की तुलना में धीमा है, है ना? लेकिन, यह वर्तमान वर्ष है, आदमी - मैं बल्कि सुंदर ढंग से और बस अनुकूलन के बारे में चिंता से लिखूंगा। यदि मुझे बाद में माइक्रो-ऑप्टिमाइज़ करने की आवश्यकता है, तो समय आने पर मैं इसके बारे में चिंता करूँगा।
इरिक बिर्कलैंड

6
मैं जोड़ना चाहूंगा कि अभी, एक साल बाद, Object.create () क्रोम में भारी रूप से अनुकूलित है, और jsperf इसे दिखाता है - यह अब सबसे तेज़ विकल्पों में से एक है। यह ठीक-ठीक दिखाता है कि आपको ऐसे माइक्रो-ऑप्टिमाइज़ेशन के साथ खुद को चिंता क्यों नहीं करनी चाहिए, और इसके बजाय बस एल्गोरिदम ध्वनि कोड लिखना चाहिए।
काइल बेकर

25

मैंने काइल की पुस्तक पढ़ी, और मुझे यह वास्तव में जानकारीपूर्ण लगा, विशेष रूप से विस्तार के बारे में कि कैसे thisबाध्य है।

पेशेवरों:

मेरे लिए, OLOO के कुछ बड़े पक्ष हैं:

1. सादगी

OLOO Object.create()एक नई ऑब्जेक्ट बनाने के लिए निर्भर करता है जो कि [[prototype]]किसी अन्य ऑब्जेक्ट के लिए है। आपको यह समझने की ज़रूरत नहीं है कि कार्यों में एक prototypeसंपत्ति है या इसके संभावित संशोधन से संबंधित किसी भी नुकसान के बारे में चिंता है।

2. क्लीनर सिंटैक्स

यह तर्कपूर्ण है, लेकिन मुझे लगता है कि OLOO सिंटैक्स (कई मामलों में) 'मानक' जावास्क्रिप्ट दृष्टिकोण से अधिक पुराना है और विशेष रूप से जब यह बहुरूपता ( super-स्टाइल कॉल) की बात आती है ।

विपक्ष:

मुझे लगता है कि डिजाइन का एक संदिग्ध बिट है (एक जो वास्तव में ऊपर 2 बिंदु पर योगदान देता है), और वह छायांकन के साथ करना है:

व्यवहार प्रतिनिधिमंडल में, हम सभी संभव नामकरण चीजों पर [[Prototype]]श्रृंखला के विभिन्न स्तरों पर समान होने से बचते हैं ।

इसके पीछे विचार यह है कि वस्तुओं के अपने अधिक विशिष्ट कार्य हैं जो तब आंतरिक रूप से कार्य को नीचे की श्रृंखला के लिए सौंपते हैं। उदाहरण के लिए, आपके पास इस पर resourceएक save()फ़ंक्शन के साथ एक ऑब्जेक्ट हो सकता है जो ऑब्जेक्ट के JSON संस्करण को सर्वर पर भेजता है, लेकिन आपके पास एक clientResourceऑब्जेक्ट भी हो सकता है जिसमें stripAndSave()फ़ंक्शन होता है, जो पहले उन गुणों को हटा देता है जिन्हें सर्वर पर नहीं भेजा जाना चाहिए ।

संभावित समस्या यह है: यदि कोई अन्य व्यक्ति साथ आता है और एक specialResourceवस्तु बनाने का फैसला करता है , पूरी प्रोटोटाइप श्रृंखला के बारे में पूरी तरह से नहीं जानता है, तो वे यथोचित * एक संपत्ति नामक अंतिम बचत के लिए टाइमस्टैम्प को बचाने का फैसला कर सकते हैं save, जो आधार save()कार्यक्षमता को छायांकित करता है resourceवस्तु प्रोटोटाइप श्रृंखला के नीचे दो लिंक:

var resource = {
  save: function () { 
    console.log('Saving');
  }
};

var clientResource = Object.create(resource);

clientResource.stripAndSave = function () {
  // Do something else, then delegate
  console.log('Stripping unwanted properties');
  this.save();
};

var specialResource = Object.create( clientResource );

specialResource.timeStampedSave = function () {
  // Set the timestamp of the last save
  this.save = Date.now();
  this.stripAndSave();
};

a = Object.create(clientResource);
b = Object.create(specialResource);

a.stripAndSave();    // "Stripping unwanted properties" & "Saving".
b.timeStampedSave(); // Error!

यह एक विशेष रूप से वंचित उदाहरण है, लेकिन मुद्दा यह है कि विशेष रूप से अन्य गुणों को छायांकित नहीं करना कुछ अजीब स्थितियों और एक थिसॉरस का भारी उपयोग हो सकता है!

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

* वास्तव में यह विशेष रूप से उचित नहीं है ( lastSavedयह बेहतर होगा, लेकिन यह सिर्फ एक उदाहरण है।)


23
मैं मानता हूं कि नाम के टकराने की संभावना एक खामी है ... लेकिन वास्तव में यह [[Prototype]]सिस्टम की खामी है, विशेष रूप से ओएलओयू की नहीं।
काइल सिम्पसन

शायद इसका जिक्र किताब में भी होना चाहिए था?
किराए

मुझे यकीन नहीं है कि यह वास्तव में समस्या का समाधान है @Ed Hinchliffe वर्णन करता है क्योंकि यह सिर्फ नाम स्थान बचाने के लिए () चलता है, लेकिन यह काम करता है codepen.io/tforward/pen/govEPr?editors/1010
Tristan Forward

मुझे लगता है कि कोड स्निपेट की अंतिम पंक्ति के b.timeStampedSave();बजाय @ ed-hinchliffe का अर्थ है a.timeStampedSave();
amangpt777

1
@ ट्रिक-फारवर्ड इस में रिक और मोर्टी को लाने के लिए धन्यवाद!
एरिक बिशर्ड

13

"यू डॉन्ट नो जेएस: दिस एंड ऑब्जेक्ट प्रोटोटाइप्स" और ओएलओओ की प्रस्तुति विचार-उत्तेजक है और मैंने किताब के माध्यम से एक टन जाना सीखा है। अन्य उत्तरों में ओएलओओ पैटर्न की खूबियों को अच्छी तरह से वर्णित किया गया है; हालाँकि, मुझे इसके साथ निम्नलिखित पालतू शिकायतें हैं (या ऐसा कुछ याद आ रहा है जो मुझे इसे प्रभावी रूप से लागू करने से रोकता है):

1

जब शास्त्रीय पैटर्न में "क्लास" "एक और" क्लास "विरासत में मिलता है, तो दो फ़ंक्शन को समान सिंटैक्स ( " फ़ंक्शन डिक्लेरेशन "या" फ़ंक्शन स्टेटमेंट " ) घोषित किया जा सकता है :

function Point(x,y) {
    this.x = x;
    this.y = y;
};

function Point3D(x,y,z) {
    Point.call(this, x,y);
    this.z = z;
};

Point3D.prototype = Object.create(Point.prototype);

इसके विपरीत, ओएलओओ पैटर्न में, आधार और व्युत्पन्न वस्तुओं को परिभाषित करने के लिए उपयोग किए जाने वाले अलग-अलग वाक्यात्मक रूप हैं:

var Point = {
    init  : function(x,y) {
        this.x = x;
        this.y = y;
    }
};


var Point3D = Object.create(Point);
Point3D.init = function(x,y,z) {
    Point.init.call(this, x, y);
    this.z = z;
};

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

2

OLOO पैटर्न में, ऑब्जेक्ट बनाना दो चरण है:

  1. कॉल Object.create
  2. ऑब्जेक्ट को इनिशियलाइज़ करने के लिए कुछ कस्टम, नॉन स्टैण्डर्ड मेथड (जिसे आपको याद रखना है क्योंकि यह एक ऑब्जेक्ट से दूसरे में भिन्न हो सकता है):

     var p2a = Object.create(Point);
    
     p2a.init(1,1);

इसके विपरीत, प्रोटोटाइप पैटर्न में आप मानक ऑपरेटर का उपयोग करते हैं new:

var p2a = new Point(1,1);

3

शास्त्रीय पैटर्न में मैं "स्टैटिक" उपयोगिता फ़ंक्शंस बना सकता हूं जो सीधे "क्लास" फ़ंक्शन पर सीधे असाइन करके "इंस्टेंट" पर लागू नहीं होता है (जैसा कि इसके विपरीत .prototype)। जैसे squareनीचे दिए गए कोड में फ़ंक्शन :

Point.square = function(x) {return x*x;};

Point.prototype.length = function() {
    return Math.sqrt(Point.square(this.x)+Point.square(this.y));
};

इसके विपरीत, OLOO पैटर्न में कोई भी "स्थिर" फ़ंक्शन उपलब्ध हैं ([प्रोटोटाइप]] श्रृंखला के माध्यम से) आपत्तियों पर भी:

var Point = {
    init  : function(x,y) {
        this.x = x;
        this.y = y;
    },
    square: function(x) {return x*x;},
    length: function() {return Math.sqrt(Point.square(this.x)+Point.square(this.y));}
};

2
आपके पहले कोड उदाहरण में कोई शाब्दिक नहीं हैं। आप शायद "शाब्दिक" शब्द का गलत अर्थ निकाल रहे हैं। बस कह रहा हूँ ...
इवान Kleshnin 15

2
2 अंक के बारे में, लेखक का तर्क है कि निर्माण और आरंभीकरण को अलग करने के लिए चिंता का एक "बेहतर" अलगाव है और इसमें कुछ दुर्लभ उपयोग का मामला हो सकता है जहां यह चमक सकता है (उदाहरण के लिए एक ऑब्जेक्ट पूल)। मुझे तर्क बहुत कमज़ोर लगते हैं।
किराए

2
2 अंक के बारे में, ओएलओ के साथ, आप एक बार में अपनी वस्तुओं को बना सकते हैं, और आरंभ करने की प्रतीक्षा कर सकते हैं, जबकि निर्माणकर्ता के साथ, आपको निर्माण पर आरंभीकरण करना होगा, इसलिए काइल इसे एक लाभ मानता है।
टैको

5

"मुझे लगा कि यह प्रत्येक obj को दूसरे पर निर्भर करता है"

जैसा कि काइल बताते हैं कि जब दो ऑब्जेक्ट [[Prototype]]जुड़े होते हैं, तो वे वास्तव में एक दूसरे पर निर्भर नहीं होते हैं; इसके बजाय वे व्यक्तिगत वस्तु हैं। आप एक ऑब्जेक्ट को दूसरे से [[Prototype]]लिंक कर रहे हैं जिसे आप अपनी इच्छानुसार कभी भी बदल सकते हैं। यदि आप [[Prototype]]ओएलओओ शैली के माध्यम से बनाई गई दो जुड़ी हुई वस्तुओं को एक दूसरे पर निर्भर होने के रूप में लेते हैं, तो आपको constructorकॉल के माध्यम से बनाई गई चीजों के बारे में भी यही सोचना चाहिए ।

var foo= {},
    bar= Object.create(foo),
    baz= Object.create(bar);


console.log(Object.getPrototypeOf(foo)) //Object.prototype

console.log(Object.getPrototypeOf(bar)) //foo

console.log(Object.getPrototypeOf(baz)) //bar

अब एक दूसरे के बारे में सोचें जो आप सोचते हैं foo barऔर bazएक-दूसरे पर निर्भर हैं?

चलिए अब ऐसा ही constructorस्टाइल कोड करते हैं-

function Foo() {}

function Bar() {}

function Baz() {}

Bar.prototype= Object.create(Foo);
Baz.prototype= Object.create(Bar);

var foo= new Foo(),
    bar= new Bar().
    baz= new Baz();

console.log(Object.getPrototypeOf(foo)) //Foo.prototype
console.log(Object.getPrototypeOf(Foo.prototype)) //Object.prototype

console.log(Object.getPrototypeOf(bar)) //Bar.prototype
console.log(Object.getPrototypeOf(Bar.prototype)) //Foo.prototype

console.log(Object.getPrototypeOf(baz)) //Baz.prototype
console.log(Object.getPrototypeOf(Baz.prototype)) //Bar.prototype

फर्क सिर्फ इतना है b / w बाद और पूर्व कोड कि बाद में है foo, bar, bazbbjects प्रत्येक-दूसरे के लिए उनके के मनमाने ढंग से वस्तुओं के माध्यम से जुड़े हुए हैं constructorसमारोह ( Foo.prototype, Bar.prototype, Baz.prototype) लेकिन पूर्व एक (में OLOOशैली) वे सीधे जुड़े हुए हैं। दोनों तरीकों तुम सिर्फ लिंक कर रहे हैं foo, bar, bazएक दूसरे के साथ, सीधे पूर्व में और परोक्ष रूप से बाद में। लेकिन, दोनों ही मामलों में ऑब्जेक्ट एक-दूसरे से स्वतंत्र होते हैं क्योंकि यह वास्तव में किसी भी वर्ग के उदाहरण की तरह नहीं होता है, जो एक बार तात्कालिक हो जाता है, उसे किसी अन्य वर्ग से विरासत में नहीं बनाया जा सकता है। आप हमेशा बदल सकते हैं कि किसी वस्तु को किस वस्तु को भी सौंपना चाहिए।

var anotherObj= {};
Object.setPrototypeOf(foo, anotherObj);

इसलिए वे सभी एक-दूसरे से स्वतंत्र हैं।

"मैं उम्मीद कर रहा था कि OLOOउस मुद्दे को हल किया जाएगा जिसमें प्रत्येक वस्तु दूसरे के बारे में कुछ नहीं जानती है।"

हाँ, यह वास्तव में संभव है-

आइए Techउपयोगिता वस्तु के रूप में उपयोग करते हैं-

 var Tech= {
     tag: "technology",
     setName= function(name) {
              this.name= name;
}
}

जितनी आप चाहते हैं उतनी वस्तुएँ बनाएँ Tech-

var html= Object.create(Tech),
     css= Object.create(Tech),
     js= Object.create(Tech);

Some checking (avoiding console.log)- 

    html.isPrototypeOf(css); //false
    html.isPrototypeOf(js); //false

    css.isPrototypeOf(html); //false
    css.isPrototypeOf(js); //false

    js.isPrototypeOf(html); //false
    js.isPrototypwOf(css); //false

    Tech.isPrototypeOf(html); //true
    Tech.isPrototypeOf(css); //true
    Tech.isPrototypeOf(js); //true

क्या आपको लगता है html, css, jsवस्तुओं प्रत्येक-दूसरे से जुड़े हैं? नहीं, वे नहीं हैं। अब देखते हैं कि हम constructorफ़ंक्शन के साथ कैसे कर सकते हैं-

function Tech() { }

Tech.prototype.tag= "technology";

Tech.prototype.setName=  function(name) {
              this.name= name;
}

जितनी आप चाहते हैं उतनी वस्तुएँ बनाएँ Tech.proptotype-

var html= new Tech(),
     css= new Tech(),
      js= new Tech();

कुछ जाँच (कंसोलिंग से बचें) -

html.isPrototypeOf(css); //false
html.isPrototypeOf(js); //false

css.isPrototypeOf(html); //false
css.isPrototypeOf(js); //false

js.isPrototypeOf(html); //false
js.isPrototypeOf(css); //false

Tech.prototype.isPrototypeOf(html); //true
Tech.prototype.isPrototypeOf(css); //true
Tech.prototype.isPrototypeOf(js); //true

आप इन कैसे सोचते हैं constructorशैली ऑब्जेक्ट ( html, css, js) वस्तुओं से अलग OLOOशैली कोड? वास्तव में वे उसी उद्देश्य की सेवा करते हैं। में OLOOशैली से एक के लिए प्रतिनिधि वस्तुओं Tech(प्रतिनिधिमंडल स्पष्ट रूप से सेट किया गया था) थोड़ी देर में constructorशैली से एक के लिए प्रतिनिधि वस्तुओं Tech.prototype(प्रतिनिधिमंडल परोक्ष स्थापित किया गया था)। अंतत: आप तीन वस्तुओं को एक-दूसरे से जोड़ते हुए, एक वस्तु से, सीधे-सीधे, प्रत्यक्ष- OLOOअप्रत्यक्ष रूप से -स्टाइल का उपयोग करते हुए, लिंकिंग को समाप्त करते हैं constructor

"जैसा है, ObjB को ObjA .. Object.create (ObjB) आदि से बनाना होगा।"

नहीं, ObjBयहाँ किसी भी वर्ग के उदाहरण (शास्त्रीय-आधारित भाषाओं में) की तरह नहीं है ObjAयह कहा जाता है कि objBवस्तु को ObjAनिर्माण के समय वस्तु के रूप में प्रत्यायोजित किया जाता है " । यदि आपने कंस्ट्रक्टर का उपयोग किया है, तो आपने समान 'युग्मन' किया होगा, हालांकि अप्रत्यक्ष रूप से .prototypeएस का उपयोग करके ।


3

@ मारकस @ भोलबेन

शायद हम ऐसा कुछ कर सकते हैं।

    const Point = {

        statics(m) { if (this !== Point) { throw Error(m); }},

        create (x, y) {
            this.statics();
            var P = Object.create(Point);
            P.init(x, y);
            return P;
        },

        init(x=0, y=0) {
            this.x = x;
            this.y = y;
        }
    };


    const Point3D = {

        __proto__: Point,

        statics(m) { if (this !== Point3D) { throw Error(m); }},

        create (x, y, z) {
            this.statics();
            var P = Object.create(Point3D);
            P.init(x, y, z);
            return P;
        },

        init (x=0, y=0, z=0) {
            super.init(x, y);
            this.z = z;
        }
    }; 

बेशक, एक पॉइंट 3 डी ऑब्जेक्ट बनाना जो पॉइंट 2 डी ऑब्जेक्ट के प्रोटोटाइप से जुड़ता है, मूर्खतापूर्ण है, लेकिन यह बिंदु के बगल में है (मैं आपके उदाहरण के अनुरूप होना चाहता था)। वैसे भी, जहां तक ​​शिकायतें जाती हैं:

  1. एसिमेट्री को ES6 के Object.setPrototypOf के साथ तय किया जा सकता है या __proto__ = ...मेरे द्वारा उपयोग किए जाने वाले अधिक। हम नियमित वस्तुओं पर भी सुपर का उपयोग कर सकते हैं, जैसा कि देखा गया है Point3D.init()। एक और तरीका कुछ ऐसा करना होगा

    const Point3D = Object.assign(Object.create(Point), {  
        ...  
    }   

    हालाँकि मुझे विशेष रूप से वाक्य रचना पसंद नहीं है।


  1. हम हमेशा सिर्फ लपेट कर सकते हैं p = Object.create(Point)और उसके बाद p.init()एक निर्माता में। उदा Point.create(x,y)। उपरोक्त कोड का उपयोग करके हम Point3Dनिम्नलिखित तरीके से एक "उदाहरण" बना सकते हैं ।

    var b = Point3D.create(1,2,3);
    console.log(b);                         // { x:1, y:2, z:3 }
    console.log(Point.isPrototypeOf(b));    // true
    console.log(Point3D.isPrototypeOf(b))   // true

  1. मैं सिर्फ ओएलओ में स्थिर तरीकों का अनुकरण करने के लिए इस हैक के साथ आया था। मुझे यकीन नहीं है कि मुझे यह पसंद है या नहीं। इसे किसी भी "स्थैतिक" विधियों के शीर्ष पर एक विशेष संपत्ति को कॉल करने की आवश्यकता होती है। उदाहरण के लिए, मैंने Point.create()विधि को स्थिर बना दिया है ।

        var p = Point.create(1,2);
        var q = p.create(4,1);          // Error!  

वैकल्पिक रूप से, ES6 प्रतीकों के साथ आप जावास्क्रिप्ट बेस कक्षाओं को सुरक्षित रूप से बढ़ा सकते हैं। इसलिए आप अपने आप को कुछ कोड सहेज सकते हैं और Object.prototype पर विशेष संपत्ति को परिभाषित कर सकते हैं। उदाहरण के लिए,

    const extendedJS = {};  

    ( function(extension) {

        const statics = Symbol('static');

        Object.defineProperty(Object.prototype, statics, {
            writable: true,
            enumerable: false,
            configurable: true,
            value(obj, message) {
                if (this !== obj)
                    throw Error(message);
            }
        });

        Object.assign(extension, {statics});

    })(extendedJS);


    const Point = {
        create (x, y) {
            this[extendedJS.statics](Point);
            ...


2

@james emanon - तो, ​​आप एकाधिक उत्तराधिकार का उल्लेख कर रहे हैं (पुस्तक "आप न जाने जेएस: यह और वस्तु प्रोटोटाइप" पुस्तक में पृष्ठ 75 पर चर्चा की गई है)। और उस तंत्र को हम उदाहरण के लिए अंडरस्कोर के "विस्तार" फ़ंक्शन में पा सकते हैं। आपके उदाहरण में बताई गई वस्तु के नाम सेब, संतरे और कैंडीज के मिश्रण से थोड़े हैं, लेकिन मैं पीछे की बात समझता हूं। मेरे अनुभव से यह OOLO संस्करण होगा:

var ObjA = {
  setA: function(a) {
    this.a = a;
  },
  outputA: function() {
    console.log("Invoking outputA - A: ", this.a);
  }
};

// 'ObjB' links/delegates to 'ObjA'
var ObjB = Object.create( ObjA );

ObjB.setB = function(b) {
   this.b = b;
}

ObjB.setA_B = function(a, b) {
    this.setA( a ); // This is obvious. 'setA' is not found in 'ObjB' so by prototype chain it's found in 'ObjA'
    this.setB( b );
    console.log("Invoking setA_B - A: ", this.a, " B: ", this.b);
};

// 'ObjC' links/delegates to 'ObjB'
var ObjC = Object.create( ObjB );

ObjC.setC = function(c) {
    this.c = c;  
};

ObjC.setA_C = function(a, c) {
    this.setA( a ); // Invoking 'setA' that is clearly not in ObjC shows that prototype chaining goes through ObjB all the way to the ObjA
    this.setC( c );
    console.log("Invoking setA_C - A: ", this.a, " C: ", this.c);
};

ObjC.setA_B_C = function(a, b, c){
    this.setA( a ); // Invoking 'setA' that is clearly not in ObjC nor ObjB shows that prototype chaining got all the way to the ObjA
    this.setB( b );
    this.setC( c );
    console.log("Invoking setA_B_C - A: ", this.a, " B: ", this.b, " C: ", this.c);
};

ObjA.setA("A1");
ObjA.outputA(); // Invoking outputA - A:  A1

ObjB.setA_B("A2", "B1"); // Invoking setA_B - A:  A2  B:  B1

ObjC.setA_C("A3", "C1"); // Invoking setA_C - A:  A3  C:  C1
ObjC.setA_B_C("A4", "B2", "C1"); // Invoking setA_B_C - A:  A4  B:  B2  C:  C1

यह सरल उदाहरण है, लेकिन दिखाया गया बिंदु यह है कि हम केवल समतल संरचना / गठन में एक साथ वस्तु का पीछा कर रहे हैं और अभी भी कई ऑब्जेक्ट से विधियों और गुणों का उपयोग करने की संभावना है। हम क्लास / "गुणों की नकल" दृष्टिकोण के साथ समान चीजें हासिल करते हैं। काइल द्वारा लिखित (पृष्ठ 114, "यह और वस्तु प्रोटोटाइप"):

दूसरे शब्दों में, वास्तविक तंत्र, जो हम जावास्क्रिप्ट में लाभ उठा सकते हैं उसकी कार्यक्षमता के लिए महत्वपूर्ण है, सभी वस्तुओं को अन्य वस्तुओं से जोड़ा जा रहा है

मैं समझता हूं कि आपके लिए और अधिक प्राकृतिक तरीका सभी "पैरेंट" (सावधान :)) ऑब्जेक्ट्स को एक जगह / फंक्शन कॉल के बजाय पूरे चेन को मॉडलिंग करना होगा।

इसके लिए हमारे अनुप्रयोगों में सोच और मॉडलिंग की समस्याओं में बदलाव की आवश्यकता है। मुझे भी इसकी आदत हो रही है। आशा है कि यह मदद करता है और काइल से अंतिम निर्णय खुद महान होगा। :)


हाँ - धन्यवाद - लेकिन मैं इस पद्धति से दूर जाने की उम्मीद कर रहा था क्योंकि जिस तरह से आपके पास है, और जिस तरह से मुझे लगा कि यह प्रत्येक obj को दूसरे पर निर्भर करता है .. मुझे उम्मीद थी कि OLOO उस मुद्दे को हल करेगा जिसमें प्रत्येक वस्तु दूसरे के बारे में कुछ नहीं जानती। जैसे, ओब्जा को ओब्जा .. ऑब्जेक्ट.क्रीट (ओबजब) आदि से बनाया जाना है .. जो बहुत अधिक युग्मित है। कोई विचार?
जेम्स ने 18

-1

@ मारकस, आपकी तरह, मैं भी ओएलओओ के लिए उत्सुक रहा हूं और आपके पहले बिंदु में वर्णित विषमता को भी नापसंद करता हूं। मैं समरूपता वापस लाने के लिए एक अमूर्त के साथ खेल रहा हूं। आप एक ऐसा link()फंक्शन बना सकते हैं जिसका इस्तेमाल जगह-जगह किया जाता है Object.create()। जब उपयोग किया जाता है, तो आपका कोड कुछ इस तरह दिख सकता है ...

var Point = {
    init  : function(x,y) {
        this.x = x;
        this.y = y;
    }
};


var Point3D = link(Point, {
    init: function(x,y,z) {
        Point.init.call(this, x, y);
        this.z = z;
    }
});

याद रखें कि Object.create()एक दूसरा पैरामीटर है जिसे अंदर पारित किया जा सकता है। यहां लिंक फ़ंक्शन है जो दूसरे पैरामीटर का लाभ उठाता है। यह भी कस्टम विन्यास के एक छोटे से अनुमति देता है ...

function link(delegate, props, propsConfig) {
  props = props || {};
  propsConfig = propsConfig || {};

  var obj = {};
  Object.keys(props).forEach(function (key) {
    obj[key] = {
      value: props[key],
      enumerable: propsConfig.isEnumerable || true,
      writable: propsConfig.isWritable || true,
      configurable: propsConfig.isConfigurable || true
    };
  });

  return Object.create(delegate, obj);
}

बेशक, मुझे लगता है कि @Kyle init()पॉइंट 3 डी ऑब्जेक्ट में फ़ंक्शन को छायांकित करने का समर्थन नहीं करेगा । ;-)


इसके माध्यम से वापस देखने में, मुझे अब लगता है कि इसके Object.assign()साथ संयोजन करके Object.create(), हम link()ऊपर दिए गए फ़ंक्शन को सरल कर सकते हैं। इसके स्थान पर, हम इसका उपयोग कर सकते हैं function create(delegate, props) { return Object.assign(Object.create(delegate), props); }:। या बेहतर अभी तक, हम इसे वास्तव में संक्षिप्त बनाने के लिए अंडरस्कोर या लॉडश का उपयोग कर सकते हैं _.create(delegate, props):।
भोलबेन

-1

क्या "दो" ऑब्जेक्ट्स से अधिक ओएलओयू का एक तरीका है .. सभी उदाहरण मैं आधारित उदाहरण से मिलकर देखता हूं (ओपी का उदाहरण देखें)। कहते हैं कि हमारे पास निम्नलिखित वस्तुएं थीं, हम एक "चौथा" ऑब्जेक्ट कैसे बना सकते हैं जिसमें 'अन्य' तीन की विशेषताएं हैं? आला ...

var Button = {
     init: function(name, cost) {
       this.buttonName = name;
       this.buttonCost = cost;
     }
}

var Shoe = {
     speed: 100
}

var Bike = {
     range: '4 miles'
}

ये वस्तुएं मनमानी हैं, और सभी प्रकार के व्यवहारों को शामिल कर सकती हैं। लेकिन जिस्ट है, हमारे पास वस्तुओं की 'एन' संख्या है, और हमारी नई वस्तु को तीनों से कुछ चाहिए।

दिए गए उदाहरणों के बजाय ala:

var newObj = Object.create(oneSingularObject);
    newObj.whatever..

लेकिन, हमारा newObject = (बटन, बाइक, जूता) ......

यह ओएलओओ में जाने के लिए क्या पैटर्न है?


1
यह "विरासत पर एहसान रचना" की तरह लगता है - एक महान रणनीति। ES6 में, आप उपयोग कर सकते हैं Object.assign()- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… । यदि _.extend()ES5 में लिखते हैं, तो आप अंडरस्कोर या लॉडश का उपयोग कर सकते हैं _.assign()। यहाँ एक उत्कृष्ट वीडियो व्याख्या करने के लिए है ... youtu.be/wfMtDGfHWpA । यदि आपके पास कोई टकराने वाले गुण हैं, तो अंतिम एक जीतता है - इसलिए आदेश मायने रखता है।
भोलेबेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.