জাভাস্ক্রিপ্টে একাধিক উত্তরাধিকার / প্রোটোটাইপ


132

আমি এমন একটি জায়গায় এসে পৌঁছেছি যেখানে জাভাস্ক্রিপ্টে আমার এক ধরণের প্রাথমিক একাধিক উত্তরাধিকার ঘটানো দরকার। (এটি একটি ভাল ধারণা বা না তা নিয়ে আমি এখানে আলোচনার জন্য নেই, সুতরাং দয়া করে দয়া করে এই মন্তব্যগুলি নিজের কাছে রাখুন।)

আমি কেবল জানতে চাইছি যে কেউ এটির (বা না) সাফল্যের সাথে চেষ্টা করেছে এবং তারা কীভাবে এটি পেরেছে।

এটিকে সিদ্ধ করার জন্য, আমার যা দরকার তা হ'ল একাধিক প্রোটোটাইপ চেইন (যেমন প্রতিটি প্রোটোটাইপের নিজস্ব যথাযথ চেইন থাকতে পারে) থেকে কোনও সম্পত্তির উত্তরাধিকারী হতে সক্ষম কোনও বিষয় থাকতে সক্ষম হওয়া , তবে প্রদত্ত অগ্রাধিকারের ক্রমে (এটি হবে) প্রথম সংজ্ঞার জন্য শৃঙ্খলে সন্ধান করুন)।

এটি তাত্ত্বিকভাবে কীভাবে সম্ভব তা প্রদর্শনের জন্য, প্রাথমিক চেইনের শেষের দিকে গৌণ চেইন সংযুক্তি দ্বারা এটি অর্জন করা যেতে পারে তবে এটি পূর্ববর্তী প্রোটোটাইপের যে কোনও একটিতে সমস্ত ঘটনা প্রভাবিত করবে এবং এটি আমি চাই না want

থটস?


1
আমি মনে করি Dojo ঘোষণা হ্যান্ডলগুলি একাধিক উত্তরাধিকার src এছাড়াও আমি একটি অনুভূতি mootools আছে এছাড়াও, এত আমার পরলোক হল কিন্তু আমি একটি দ্রুত পঠিত যাচ্ছি এই Dojo যেমন প্রস্তাব দেওয়া
TI তৈরি

ট্রেইটজেএসকে দেখুন ( লিঙ্ক 1 , লিঙ্ক 2 ) এটি একাধিক উত্তরাধিকার এবং মিক্সিন্সের সত্যিই ভাল বিকল্প ...
সিএমএস

1
@ পয়েন্টটি কারণ এটি খুব গতিশীল নয়। আমি প্যারেন্ট শৃঙ্খলাগুলির সাথে সাথে ঘটে যাওয়া পরিবর্তনগুলি নিতে সক্ষম হতে চাই। তবে এটি বলেছে, এটি সম্ভব না হলে আমাকে এটিকে অবলম্বন করতে হতে পারে।
devios1


1
এটি সম্পর্কে একটি আকর্ষণীয় পঠন: ওয়েবরেফ্লেশন.ব্লগস্পট.কম.উইক
নোবিতা

উত্তর:


49

প্রক্সি অবজেক্টগুলি ব্যবহার করে একামাস্ক্রিপ্ট in এ একাধিক উত্তরাধিকার অর্জন করা যায়

বাস্তবায়ন

function getDesc (obj, prop) {
  var desc = Object.getOwnPropertyDescriptor(obj, prop);
  return desc || (obj=Object.getPrototypeOf(obj) ? getDesc(obj, prop) : void 0);
}
function multiInherit (...protos) {
  return Object.create(new Proxy(Object.create(null), {
    has: (target, prop) => protos.some(obj => prop in obj),
    get (target, prop, receiver) {
      var obj = protos.find(obj => prop in obj);
      return obj ? Reflect.get(obj, prop, receiver) : void 0;
    },
    set (target, prop, value, receiver) {
      var obj = protos.find(obj => prop in obj);
      return Reflect.set(obj || Object.create(null), prop, value, receiver);
    },
    *enumerate (target) { yield* this.ownKeys(target); },
    ownKeys(target) {
      var hash = Object.create(null);
      for(var obj of protos) for(var p in obj) if(!hash[p]) hash[p] = true;
      return Object.getOwnPropertyNames(hash);
    },
    getOwnPropertyDescriptor(target, prop) {
      var obj = protos.find(obj => prop in obj);
      var desc = obj ? getDesc(obj, prop) : void 0;
      if(desc) desc.configurable = true;
      return desc;
    },
    preventExtensions: (target) => false,
    defineProperty: (target, prop, desc) => false,
  }));
}

ব্যাখ্যা

একটি প্রক্সি অবজেক্টে একটি টার্গেট অবজেক্ট এবং কিছু ফাঁদ থাকে, যা মৌলিক ক্রিয়াকলাপের জন্য কাস্টম আচরণকে সংজ্ঞায়িত করে।

অন্যটি থেকে উত্তরাধিকারসূত্রে প্রাপ্ত কোনও সামগ্রী তৈরি করার সময় আমরা ব্যবহার করি Object.create(obj)। তবে objএক্ষেত্রে আমরা একাধিক উত্তরাধিকার চাই, সুতরাং আমি এর পরিবর্তে এমন একটি প্রক্সি ব্যবহার করব যা মৌলিক ক্রিয়াকলাপগুলিকে উপযুক্ত অবজেক্টে পুনঃনির্দেশ করবে।

আমি এই ফাঁদ ব্যবহার:

  • hasফাঁদ জন্য একটি ফাঁদ হয় inঅপারেটর । আমি someঅন্তত একটি প্রোটোটাইপটিতে সম্পত্তি রয়েছে কিনা তা পরীক্ষা করতে ব্যবহার করি ।
  • getফাঁদ সম্পত্তি মান পাবার জন্য একটি ফাঁদ। আমি findপ্রথম প্রোটোটাইপটি সন্ধান করতে ব্যবহার করি যার মধ্যে সেই সম্পত্তি রয়েছে এবং আমি মানটি ফিরিয়ে দিই বা উপযুক্ত প্রাপ্তিতে কলকারীকে কল করি। এটি দ্বারা পরিচালিত হয় Reflect.get। কোনও প্রোটোটাইপতে সম্পত্তি না থাকলে আমি ফিরে আসি undefined
  • setফাঁদ সম্পত্তি মান সেট করার জন্য একটি ফাঁদ। আমি findপ্রথম প্রোটোটাইপটি সন্ধান করতে ব্যবহার করি যার মধ্যে সেই সম্পত্তি রয়েছে এবং আমি এটির সেটারটিকে যথাযথ রিসিভারে কল করি। যদি কোনও সেটার না থাকে বা কোনও প্রোটোটাইপতে সম্পত্তি থাকে না, মানটি উপযুক্ত রিসিভারের উপর সংজ্ঞায়িত করা হয়। এটি দ্বারা পরিচালিত হয় Reflect.set
  • enumerateফাঁদ জন্য একটি ফাঁদ হয় for...inলুপ । আমি প্রথম প্রোটোটাইপ, তারপরে দ্বিতীয় থেকে এবং এই জাতীয় আরও অনেকগুলি গুণাবলীর পুনরাবৃত্তি করি। কোনও সম্পত্তি পুনরাবৃত্তি হওয়ার পরে, এটি পুনরায় পুনরুক্তি না করার জন্য আমি এটি একটি হ্যাশ টেবিলের মধ্যে সঞ্চয় করি।
    সতর্কতা : এই ফাঁদটি ES7 খসড়াটিতে সরিয়ে ফেলা হয়েছে এবং ব্রাউজারগুলিতে হ্রাস করা হয়েছে।
  • ownKeysফাঁদ জন্য একটি ফাঁদ হয় Object.getOwnPropertyNames()। ES7 যেহেতু, for...inলুপগুলি [[getPrototypeOf]] কে কল করতে থাকে এবং প্রত্যেকের নিজস্ব সম্পত্তি পেয়ে থাকে। সুতরাং এটি সমস্ত প্রোটোটাইপের বৈশিষ্ট্যগুলিকে পুনরাবৃত্তি করার জন্য, আমি এই জালটি সমস্ত উত্তরাধিকার সূত্রে প্রাপ্ত সম্পত্তি হিসাবে নিজের সম্পত্তি হিসাবে প্রদর্শিত করতে তৈরি করি।
  • getOwnPropertyDescriptorফাঁদ জন্য একটি ফাঁদ হয় Object.getOwnPropertyDescriptor()। সমস্ত গণনামূলক বৈশিষ্ট্য ownKeysফাঁদে নিজের বৈশিষ্ট্যগুলির মতো উপস্থিত হওয়া যথেষ্ট নয়, for...inলুপগুলি বর্ণনাকারী সেগুলি অগণনীয় কিনা তা পরীক্ষা করার জন্য পাবেন। সুতরাং আমি findসেই প্রথম প্রোটোটাইপটি সন্ধান করতে ব্যবহার করি যার মধ্যে সেই সম্পত্তি রয়েছে এবং আমি সম্পত্তিটির মালিক না পাওয়া পর্যন্ত আমি এর প্রোটোটাইপিকাল চেইনটি পুনরাবৃত্তি করি এবং আমি এর বিবরণী ফিরিয়ে না নিই। কোনও প্রোটোটাইপতে সম্পত্তি না থাকলে আমি ফিরে আসি undefined। বর্ণনাকারীকে এটিকে কনফিগারযোগ্য করার জন্য সংশোধন করা হয়েছে, অন্যথায় আমরা কিছু প্রক্সি আক্রমণকারীকে ভেঙে ফেলতে পারি।
  • preventExtensionsএবং definePropertyযাত্রীর সঙ্গের নিজলটবহর শুধুমাত্র প্রক্সি লক্ষ্য পরিবর্তন থেকে এই অভিযান প্রতিরোধ অন্তর্ভুক্ত করা হয়। অন্যথায় আমরা কিছু প্রক্সি আক্রমণকারীদের ভেঙে যেতে পারি।

আরও ফাঁদ পাওয়া যায়, যা আমি ব্যবহার করি না

  • getPrototypeOfফাঁদ যোগ করা যায়নি, কিন্তু সেখানে একাধিক এগুলির নমুনা ফিরে যাওয়ার কোন সঠিক উপায়। এর দ্বারা বোঝা যাচ্ছে instanceofযে কোনও কাজ করবে না। অতএব, আমি এটিকে লক্ষ্যটির প্রোটোটাইপ পেতে দিই, যা প্রাথমিকভাবে শূন্য।
  • setPrototypeOfফাঁদ জুড়েছে এবং বস্তুর একটি অ্যারে গ্রহণ, যা এগুলির নমুনা প্রতিস্থাপন করবে যেতে পারে। এটি পাঠকের জন্য অনুশীলন হিসাবে রেখে দেওয়া হয়েছে। এখানে আমি কেবলমাত্র লক্ষ্যটির প্রোটোটাইপটি সংশোধন করতে দিয়েছি, যা কোনও কার্যকর নয় কারণ কোনও ট্র্যাপ লক্ষ্য ব্যবহার করে না।
  • deletePropertyফাঁদ নিজের বৈশিষ্ট্য মুছে ফেলার জন্য একটি ফাঁদ। প্রক্সিটি উত্তরাধিকারের প্রতিনিধিত্ব করে, তাই এটি বেশি অর্থবোধ করে না। আমি এটি লক্ষ্যবস্তুতে মোছার চেষ্টা করতে দিয়েছি, যার কোনওভাবেই সম্পত্তি না থাকা উচিত।
  • isExtensibleফাঁদ extensibility পাবার জন্য একটি ফাঁদ। একটি আক্রমণকারী এটি লক্ষ্য হিসাবে একই এক্সটেনসিবলিটিকে ফিরিয়ে দিতে বাধ্য করে, এটি খুব বেশি কার্যকর নয়। সুতরাং আমি কেবল এটি অপারেশনটিকে লক্ষ্যকে পুনর্নির্দেশ করতে দিই, যা এক্সটেনসিবল হবে।
  • applyএবং constructযাত্রীর সঙ্গের নিজলটবহর কলিং বা শুরু করতে গিয়ে জন্য যাত্রীর সঙ্গের নিজলটবহর হয়। এগুলি কেবল তখন কার্যকর হয় যখন লক্ষ্য কোনও ফাংশন বা নির্মাতা হয়।

উদাহরণ

// Creating objects
var o1, o2, o3,
    obj = multiInherit(o1={a:1}, o2={b:2}, o3={a:3, b:3});

// Checking property existences
'a' in obj; // true   (inherited from o1)
'b' in obj; // true   (inherited from o2)
'c' in obj; // false  (not found)

// Setting properties
obj.c = 3;

// Reading properties
obj.a; // 1           (inherited from o1)
obj.b; // 2           (inherited from o2)
obj.c; // 3           (own property)
obj.d; // undefined   (not found)

// The inheritance is "live"
obj.a; // 1           (inherited from o1)
delete o1.a;
obj.a; // 3           (inherited from o3)

// Property enumeration
for(var p in obj) p; // "c", "b", "a"

1
এমন কিছু পারফরম্যান্স সমস্যা নেই যা সাধারণ স্কেল অ্যাপ্লিকেশনগুলিতেও প্রাসঙ্গিক হয়ে উঠবে?
টোমা জ্যাটো - মনিকা

1
@ টোম্যাজাতো এটি কোনও সাধারণ অবজেক্টের ডেটা বৈশিষ্ট্যের তুলনায় ধীর হবে তবে আমার মনে হয় না এটি অ্যাক্সেসরের বৈশিষ্ট্যের চেয়ে আরও খারাপ হবে।
ওরিওল

টিআইএল:multiInherit(o1={a:1}, o2={b:2}, o3={a:3, b:3})
রক্তাক্তনাকলস

4
কী চলছে তার আরও ভাল ধারণা পেতে আমি "একাধিক প্রতিনিধি" দ্বারা "একাধিক উত্তরাধিকার" প্রতিস্থাপনের বিষয়টি বিবেচনা করব। আপনার বাস্তবায়নের মূল ধারণাটি এটি যে প্রক্সিটি বার্তাটি পেশ করার জন্য (বা ফরোয়ার্ড) করার জন্য সঠিকভাবে সঠিক অবজেক্টটি বেছে নিচ্ছে । আপনার সমাধানের শক্তি হ'ল আপনি লক্ষ্য প্রোটোটাইপ / গতিশীলভাবে প্রসারিত করতে পারেন। অন্যান্য উত্তরগুলি সংক্ষিপ্তকরণ (আলা Object.assign) ব্যবহার করছে বা একেবারে ভিন্ন গ্রাফ পাচ্ছে, শেষ অবধি তারা সকলেই অবজেক্টের মধ্যে এক-একমাত্র প্রোটোটাইপ চেইন পাচ্ছে। প্রক্সি সমাধানটি রানটাইম শাখা সরবরাহ করে এবং এই শিলা!
স্মিনিটোলি

কর্মক্ষমতা সম্পর্কে, আপনি যদি একাধিক অবজেক্টের উত্তরাধিকার সূত্রে কোনও বস্তু তৈরি করেন যা একাধিক বস্তু থেকে উত্তরাধিকার সূত্রে আসে, তবে তা ঘনিষ্ঠ হয়ে যাবে। হ্যাঁ, এটি ধীর হবে। তবে সাধারণ ক্ষেত্রে আমি মনে করি না যে এটি খারাপ হবে।
ওরিওল

16

আপডেট (2019): আসল পোস্টটি বেশ পুরানো হয়ে উঠছে। এই নিবন্ধটি (এখন ইন্টারনেট সংরক্ষণাগার লিঙ্ক, যেহেতু ডোমেন চলে গেছে) এবং এর সাথে সম্পর্কিত গিটহাব লাইব্রেরি একটি ভাল আধুনিক পদ্ধতির।

মূল পোস্ট: একাধিক উত্তরাধিকার [সম্পাদনা, প্রকারের যথাযথ উত্তরাধিকার নয়, তবে সম্পত্তিগুলির; মিশ্রিনস] জাভাস্ক্রিপ্টে বেশ সোজা হয়ে থাকে যদি আপনি জেনেরিক-অবজেক্টের চেয়ে তৈরি প্রোটোটাইপ ব্যবহার করেন। উত্তরাধিকার সূত্রে এখানে দুটি অভিভাবক শ্রেণি রয়েছে:

function FoodPrototype() {
    this.eat = function () {
        console.log("Eating", this.name);
    };
}
function Food(name) {
    this.name = name;
}
Food.prototype = new FoodPrototype();


function PlantPrototype() {
    this.grow = function () {
        console.log("Growing", this.name);
    };
}
function Plant(name) {
    this.name = name;
}
Plant.prototype = new PlantPrototype();

নোট করুন যে আমি প্রতিটি ক্ষেত্রে একই "নাম" সদস্য ব্যবহার করেছি, যা "নাম" কীভাবে পরিচালনা করা উচিত তা সম্পর্কে বাবা-মা যদি একমত না হন তবে সমস্যা হতে পারে। তবে তারা এক্ষেত্রে সামঞ্জস্যপূর্ণ (অনর্থক, সত্যই)।

এখন আমাদের কেবল একটি ক্লাস দরকার যা উভয়ের কাছ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত। প্রোটোটাইপ এবং অবজেক্ট কনস্ট্রাক্টরের জন্য কনস্ট্রাক্টর ফাংশন (নতুন কীওয়ার্ড ব্যবহার না করে) কল করে উত্তরাধিকার সূচনা করা হয় । প্রথমত, প্রোটোটাইপটি প্যারেন্ট প্রোটোটাইপগুলির কাছ থেকে উত্তরাধিকারী হতে হয়

function FoodPlantPrototype() {
    FoodPrototype.call(this);
    PlantPrototype.call(this);
    // plus a function of its own
    this.harvest = function () {
        console.log("harvest at", this.maturity);
    };
}

এবং কনস্ট্রাক্টরকে পিতামাত্ত কনস্ট্রাক্টরের কাছ থেকে উত্তরাধিকারী হতে হবে:

function FoodPlant(name, maturity) {
    Food.call(this, name);
    Plant.call(this, name);
    // plus a property of its own
    this.maturity = maturity;
}

FoodPlant.prototype = new FoodPlantPrototype();

এখন আপনি বিভিন্ন পরিস্থিতিতে বৃদ্ধি, খাওয়া এবং ফসল কাটাতে পারেন:

var fp1 = new FoodPlant('Radish', 28);
var fp2 = new FoodPlant('Corn', 90);

fp1.grow();
fp2.grow();
fp1.harvest();
fp1.eat();
fp2.harvest();
fp2.eat();

প্রোটোটাইপগুলি বিল্ট ইন দিয়ে আপনি এটি করতে পারেন? (অ্যারে, স্ট্রিং, সংখ্যা)
টোমা জ্যাটো - মনিকা পুনর্নির্মাণ

আমি মনে করি না যে বিল্ট-ইন প্রোটোটাইপগুলিতে আপনি কল করতে পারেন এমন কনস্ট্রাক্টর রয়েছে।
রায় জে

ঠিক আছে, আমি করতে পারি Array.call(...)তবে আমি যা যা করি তা প্রভাবিত করে না বলে মনে হয় this
টোমা জ্যাটো - মনিকা

@ টমজাটো আপনি করতে পেরেছিলেনArray.prototype.constructor.call()
রায় জে

1
@ অভিষেকগুপ্ত আমাকে জানাতে ধন্যবাদ Thanks সংরক্ষণাগারিত ওয়েব পৃষ্ঠার লিঙ্কের সাথে আমি লিঙ্কটি প্রতিস্থাপন করেছি।
রায় জে

7

এটি Object.createএকটি আসল প্রোটোটাইপ চেইন তৈরি করতে ব্যবহার করে:

function makeChain(chains) {
  var c = Object.prototype;

  while(chains.length) {
    c = Object.create(c);
    $.extend(c, chains.pop()); // some function that does mixin
  }

  return c;
}

উদাহরণ স্বরূপ:

var obj = makeChain([{a:1}, {a: 2, b: 3}, {c: 4}]);

ফিরে আসবে:

a: 1
  a: 2
  b: 3
    c: 4
      <Object.prototype stuff>

যাতে obj.a === 1, obj.b === 3ইত্যাদি


কেবলমাত্র একটি দ্রুত অনুমানমূলক প্রশ্ন: আমি সংখ্যা এবং অ্যারে প্রোটোটাইপগুলি (মজাদার জন্য) মিশ্রিত করে ভেক্টর শ্রেণি তৈরি করতে চেয়েছিলাম। এটি আমাকে উভয় অ্যারে সূচক এবং গণিত অপারেটর দেবে। কিন্তু এটা কি কাজ করবে?
টোমা জ্যাটো - মনিকা

@ টোমাজাটো, আপনি যদি সাবক্লাসিং অ্যারেগুলি সন্ধান করছেন তবে এই নিবন্ধটি পরীক্ষা করে দেখার মতো ; এটি আপনাকে কিছুটা মাথা ব্যাথা বাঁচাতে পারে। শুভকামনা!
ব্যবহারকারী 3276552

5

জন রেসিগের একটি শ্রেণিবদ্ধ কাঠামো বাস্তবায়ন আমার পছন্দ: http://ejohn.org/blog/simple-javascript-inheritance/

এটি কেবল এমন কিছুতে প্রসারিত করা যেতে পারে:

Class.extend = function(prop /*, prop, prop, prop */) {
    for( var i=1, l=arguments.length; i<l; i++ ){
        prop = $.extend( prop, arguments[i] );
    }

    // same code
}

যা আপনাকে উত্তরাধিকারসূত্রে একাধিক বস্তুতে যেতে দেয়। আপনি instanceOfএখানে সক্ষমতা হারাতে চলেছেন তবে আপনি যদি একাধিক উত্তরাধিকার চান তবে এটি একটি প্রদত্ত।


উপরের আমার পরিবর্তে বিশৃঙ্খল উদাহরণটি https://github.com/cwolves/Fetch/blob/master/support/plugins/klass/klass.js এ উপলব্ধ

মনে রাখবেন যে সেই ফাইলে কিছু ডেড কোড রয়েছে তবে আপনি যদি একবার দেখতে চান তবে এটি একাধিক উত্তরাধিকারের অনুমতি দেয়।


যদি আপনি শৃঙ্খলিত উত্তরাধিকার চান (একাধিক উত্তরাধিকার নয়, তবে বেশিরভাগ মানুষের ক্ষেত্রে এটি একই জিনিস) তবে এটি ক্লাসের মতো সম্পন্ন করা যেতে পারে:

var newClass = Class.extend( cls1 ).extend( cls2 ).extend( cls3 )

যা মূল প্রোটোটাইপ চেইন সংরক্ষণ করবে, তবে আপনার প্রচুর অর্থহীন কোডও চলবে।


7
এটি একীভূত অগভীর ক্লোন তৈরি করে। "উত্তরাধিকারসূত্রে" অবজেক্টগুলিতে একটি নতুন সম্পত্তি যুক্ত করার ফলে নতুন সম্পত্তিটি উত্পন্ন বস্তুর উপর প্রদর্শিত হবে না, যেমন এটি সত্য প্রোটোটাইপ উত্তরাধিকার হিসাবে।
ড্যানিয়েল আরউইকার

@ ড্যানিয়েলআরউইকার - সত্য, তবে যদি আপনি এক শ্রেণীর দুটি শ্রেণি থেকে প্রাপ্ত "একাধিক উত্তরাধিকার" চান তবে সত্যিকারের বিকল্প নেই। কেবলমাত্র ক্লাসে এক সাথে শৃঙ্খলাবদ্ধ হওয়া প্রতিবিম্বিত করার পরিবর্তিত উত্তর বেশিরভাগ ক্ষেত্রে একই জিনিস।
মার্ক কাহন

দেখে মনে হচ্ছে আপনার গিটএইচইউবি চলে গেছে আপনি কি এখনও github.com/cwolves/Fetch/blob/master/support/plugins/klass/… ভাগ করে নিতে যত্ন নিলে আমি এটার দিকে তাকিয়ে কিছু মনে করব না?
জেসনডাভিস 13

4

একাধিক উত্তরাধিকারের জাভাস্ক্রিপ্ট ফ্রেমওয়ার্ক প্রয়োগের সাথে বিভ্রান্ত হবেন না।

আপনাকে কেবলমাত্র নির্দিষ্ট প্রোটোটাইপ অবজেক্ট এবং বৈশিষ্ট্যগুলির সাথে প্রতিবার একটি নতুন অবজেক্ট তৈরি করতে অবজেক্ট.ক্রিট () ব্যবহার করতে হবে, তারপরে অবজেক্ট.প্রোটোটাইপ কনস্ট্রাক্টরের প্রতিটি পদক্ষেপ পরিবর্তন করার বিষয়ে নিশ্চিত হন যদি আপনি ইনস্ট্যান্ট করার পরিকল্পনা করে Bথাকেন ভবিষ্যত।

উদাহরণ বৈশিষ্ট্যগুলি উত্তরাধিকারী করার জন্য thisAএবং thisBআমরা প্রতিটি অবজেক্ট ফাংশন শেষে Function.prototype.call () ব্যবহার করি । যদি আপনি কেবল প্রোটোটাইপ উত্তরাধিকার সূত্রে যত্ন নেন তবে এটি optionচ্ছিক।

নিম্নলিখিত কোডটি কোথাও চালনা করুন এবং পর্যবেক্ষণ করুন objC:

function A() {
  this.thisA = 4; // objC will contain this property
}

A.prototype.a = 2; // objC will contain this property

B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;

function B() {
  this.thisB = 55; // objC will contain this property

  A.call(this);
}

B.prototype.b = 3; // objC will contain this property

C.prototype = Object.create(B.prototype);
C.prototype.constructor = C;

function C() {
  this.thisC = 123; // objC will contain this property

  B.call(this);
}

C.prototype.c = 2; // objC will contain this property

var objC = new C();
  • B থেকে প্রোটোটাইপ উত্তরাধিকার সূত্রে প্রাপ্ত A
  • C থেকে প্রোটোটাইপ উত্তরাধিকার সূত্রে প্রাপ্ত B
  • objC একটি উদাহরণ C

এটি উপরের পদক্ষেপগুলির একটি ভাল ব্যাখ্যা:

জাভাস্ক্রিপ্টে ওওপি: আপনার জানা দরকার


যদিও এই নতুন বৈশিষ্ট্যে সমস্ত সম্পত্তি অনুলিপি করে না? সুতরাং আপনার যদি দুটি প্রোটোটাইপ, এ এবং বি থাকে এবং আপনি সেগুলিকে দুটি সিটিতে পুনরায় তৈরি করেন, এ এর ​​সম্পত্তি পরিবর্তন করা সেই সম্পত্তিকে সি এবং ভিসার বিপরীতে প্রভাব ফেলবে না। আপনি স্মৃতিতে সঞ্চিত এ এবং বি এর সমস্ত বৈশিষ্ট্যের অনুলিপিটি শেষ করবেন। এটি একই পারফরম্যান্সের মতো হবে যদি আপনি এ এবং বি এর সমস্ত বৈশিষ্ট্য সিটিতে শক্তভাবে কোডড করে রেখেছিলেন তবে এটি পাঠযোগ্যতার জন্য দুর্দান্ত, এবং সম্পত্তি অনুসন্ধানের জন্য প্যারেন্ট অবজেক্টগুলিতে ভ্রমণ করতে হবে না, তবে এটি আসলে উত্তরাধিকার নয় - আরও ক্লোনিংয়ের মতো। এ-তে সম্পত্তি পরিবর্তন করা সি
ফ্রাঙ্ক

2

আমি কোনওভাবেই জাভাস্ক্রিপ্ট ওওপি-তে বিশেষজ্ঞ নই, তবে আমি যদি আপনাকে সঠিকভাবে বুঝতে পারি তবে আপনি (সিউডো কোড) এর মতো কিছু চান:

Earth.shape = 'round';
Animal.shape = 'random';

Cat inherit from (Earth, Animal);

Cat.shape = 'random' or 'round' depending on inheritance order;

সেক্ষেত্রে আমি এরকম কিছু চেষ্টা করব:

var Earth = function(){};
Earth.prototype.shape = 'round';

var Animal = function(){};
Animal.prototype.shape = 'random';
Animal.prototype.head = true;

var Cat = function(){};

MultiInherit(Cat, Earth, Animal);

console.log(new Cat().shape); // yields "round", since I reversed the inheritance order
console.log(new Cat().head); // true

function MultiInherit() {
    var c = [].shift.call(arguments),
        len = arguments.length
    while(len--) {
        $.extend(c.prototype, new arguments[len]());
    }
}

1
এটি কি প্রথম প্রোটোটাইপটি বাছাই করে বাকিগুলি উপেক্ষা করছে না? c.prototypeএকাধিকবার সেট করা একাধিক প্রোটোটাইপ দেয় না। উদাহরণস্বরূপ, যদি আপনি ছিল Animal.isAlive = true, Cat.isAliveএখনো অনির্দিষ্ট করা হবে।
devios1

হ্যাঁ, আমি প্রোটোটাইপগুলি মিশিয়ে বোঝানোর অর্থ দিয়েছিলাম, সংশোধন করেছি ... (আমি এখানে jQuery এর প্রসার ব্যবহার করেছি, তবে আপনি ছবিটি পেয়েছেন)
ডেভিড হেলসিং

2

জাভা স্ক্রিপ্টে একাধিক উত্তরাধিকার বাস্তবায়ন সম্ভব, যদিও খুব কম লাইব্রেরি এটি করে।

আমি রিং.জেএসকে নির্দেশ করতে পারি , এটি আমার একমাত্র উদাহরণ।


2

আমি আজ এটিতে অনেক কাজ করেছিলাম এবং ইএস 6 এ নিজেকে অর্জন করার চেষ্টা করছিলাম। আমি যেভাবে এটি করেছি ব্রাউজারিফাই, বাবেল এবং তারপরে আমি ওয়ালাবির সাথে এটি পরীক্ষা করেছি এবং দেখে মনে হচ্ছে এটি কাজ করে। আমার লক্ষ্য হ'ল বর্তমান অ্যারে প্রসারিত করা, ES6, ES7 অন্তর্ভুক্ত করা এবং অডিও ডেটা নিয়ে কাজ করার জন্য প্রোটোটাইপে আমার প্রয়োজনীয় কিছু অতিরিক্ত কাস্টম বৈশিষ্ট্য যুক্ত করা।

ওয়ালাবি আমার ৪ টি পরীক্ষায় পাস করেছে। উদাহরণ.js ফাইলটি কনসোলে আটকানো যেতে পারে এবং আপনি দেখতে পাবেন যে 'অন্তর্ভুক্ত' সম্পত্তি শ্রেণীর প্রোটোটাইপে রয়েছে। আমি এখনও আগামীকাল আরও পরীক্ষা করতে চাই।

আমার পদ্ধতিটি এখানে: (আমি সম্ভবত কিছুটা ঘুমানোর পরে মডিউল হিসাবে রিফ্যাক্টর এবং পুনঃস্থাপন করব!)

var includes = require('./polyfills/includes');
var keys =  Object.getOwnPropertyNames(includes.prototype);
keys.shift();

class ArrayIncludesPollyfills extends Array {}

function inherit (...keys) {
  keys.map(function(key){
      ArrayIncludesPollyfills.prototype[key]= includes.prototype[key];
  });
}

inherit(keys);

module.exports = ArrayIncludesPollyfills

গিথুব রেপো: https://github.com/danieldram/array-includes-polyfill


2

আমি মনে করি এটি হাস্যকরভাবে সহজ is এখানে সমস্যাটি হ'ল শিশু শ্রেণি কেবলমাত্র instanceofআপনার কল করা প্রথম শ্রেণীর জন্য উল্লেখ করবে

https://jsfiddle.net/1033xzyt/19/

function Foo() {
  this.bar = 'bar';
  return this;
}
Foo.prototype.test = function(){return 1;}

function Bar() {
  this.bro = 'bro';
  return this;
}
Bar.prototype.test2 = function(){return 2;}

function Cool() {
  Foo.call(this);
  Bar.call(this);

  return this;
}

var combine = Object.create(Foo.prototype);
$.extend(combine, Object.create(Bar.prototype));

Cool.prototype = Object.create(combine);
Cool.prototype.constructor = Cool;

var cool = new Cool();

console.log(cool.test()); // 1
console.log(cool.test2()); //2
console.log(cool.bro) //bro
console.log(cool.bar) //bar
console.log(cool instanceof Foo); //true
console.log(cool instanceof Bar); //false

1

নীচে কোডটি যা একাধিক উত্তরাধিকারের জন্য সমর্থন দেখায় তা চেক করুন। প্রোটিটিপাল ইনহিরিটেন্স ব্যবহার করে সম্পন্ন হয়েছে

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

    this.name = name;
}

function B(age) {
    this.age = age;
}
B.prototype.setAge = function (age) {
    this.age = age;
}

function AB(name, age) {
    A.prototype.setName.call(this, name);
    B.prototype.setAge.call(this, age);
}

AB.prototype = Object.assign({}, Object.create(A.prototype), Object.create(B.prototype));

AB.prototype.toString = function () {
    return `Name: ${this.name} has age: ${this.age}`
}

const a = new A("shivang");
const b = new B(32);
console.log(a.name);
console.log(b.age);
const ab = new AB("indu", 27);
console.log(ab.toString());

1

ক্লাসগুলি একাধিক উত্তরাধিকারের সাথে সংজ্ঞায়িত করার অনুমতি দেওয়ার জন্য আমার যথেষ্ট ফাংশন রয়েছে। এটি নিম্নলিখিত মত কোডের জন্য অনুমতি দেয়। সামগ্রিকভাবে আপনি জাভাস্ক্রিপ্টে স্থানীয় ক্লাসিং কৌশলগুলি থেকে সম্পূর্ণ প্রস্থান লক্ষ্য করবেন (উদাহরণস্বরূপ আপনি classকীওয়ার্ডটি কখনই দেখতে পাবেন না ):

let human = new Running({ name: 'human', numLegs: 2 });
human.run();

let airplane = new Flying({ name: 'airplane', numWings: 2 });
airplane.fly();

let dragon = new RunningFlying({ name: 'dragon', numLegs: 4, numWings: 6 });
dragon.takeFlight();

এভাবে আউটপুট উত্পাদন করতে:

human runs with 2 legs.
airplane flies away with 2 wings!
dragon runs with 4 legs.
dragon flies away with 6 wings!

এখানে শ্রেণীর সংজ্ঞাগুলি দেখতে কেমন:

let Named = makeClass('Named', {}, () => ({
  init: function({ name }) {
    this.name = name;
  }
}));

let Running = makeClass('Running', { Named }, protos => ({
  init: function({ name, numLegs }) {
    protos.Named.init.call(this, { name });
    this.numLegs = numLegs;
  },
  run: function() {
    console.log(`${this.name} runs with ${this.numLegs} legs.`);
  }
}));

let Flying = makeClass('Flying', { Named }, protos => ({
  init: function({ name, numWings }) {
    protos.Named.init.call(this, { name });
    this.numWings = numWings;
  },
  fly: function( ){
    console.log(`${this.name} flies away with ${this.numWings} wings!`);
  }
}));

let RunningFlying = makeClass('RunningFlying', { Running, Flying }, protos => ({
  init: function({ name, numLegs, numWings }) {
    protos.Running.init.call(this, { name, numLegs });
    protos.Flying.init.call(this, { name, numWings });
  },
  takeFlight: function() {
    this.run();
    this.fly();
  }
}));

আমরা দেখতে পাচ্ছি যে makeClassফাংশনটি ব্যবহার করে প্রতিটি শ্রেণির সংজ্ঞা Objectপিতামাতা-শ্রেণিতে ম্যাপযুক্ত পিতৃত-শ্রেণীর নামের একটি গ্রহণ করে । এটি এমন কোনও ফাংশনও গ্রহণ করে যা Objectশ্রেণীর সংজ্ঞায়িত হওয়ার জন্য একটি বৈশিষ্ট্যযুক্ত বৈশিষ্ট্য দেয়। এই ফাংশনটির একটি প্যারামিটার রয়েছেprotos রয়েছে, যার মধ্যে প্যারেন্ট-ক্লাসগুলির দ্বারা নির্ধারিত কোনও সম্পত্তি অ্যাক্সেস করার জন্য পর্যাপ্ত তথ্য রয়েছে।

প্রয়োজনীয় চূড়ান্ত টুকরাটি হ'ল makeClassফাংশনটি, যা বেশ কিছুটা কাজ করে। বাকি কোড সহ এটি এখানে। আমি makeClassবেশ ভারী মন্তব্য করেছি :

let makeClass = (name, parents={}, propertiesFn=()=>({})) => {
  
  // The constructor just curries to a Function named "init"
  let Class = function(...args) { this.init(...args); };
  
  // This allows instances to be named properly in the terminal
  Object.defineProperty(Class, 'name', { value: name });
  
  // Tracking parents of `Class` allows for inheritance queries later
  Class.parents = parents;
  
  // Initialize prototype
  Class.prototype = Object.create(null);
  
  // Collect all parent-class prototypes. `Object.getOwnPropertyNames`
  // will get us the best results. Finally, we'll be able to reference
  // a property like "usefulMethod" of Class "ParentClass3" with:
  // `parProtos.ParentClass3.usefulMethod`
  let parProtos = {};
  for (let parName in parents) {
    let proto = parents[parName].prototype;
    parProtos[parName] = {};
    for (let k of Object.getOwnPropertyNames(proto)) {
      parProtos[parName][k] = proto[k];
    }
  }
  
  // Resolve `properties` as the result of calling `propertiesFn`. Pass
  // `parProtos`, so a child-class can access parent-class methods, and
  // pass `Class` so methods of the child-class have a reference to it
  let properties = propertiesFn(parProtos, Class);
  properties.constructor = Class; // Ensure "constructor" prop exists
  
  // If two parent-classes define a property under the same name, we
  // have a "collision". In cases of collisions, the child-class *must*
  // define a method (and within that method it can decide how to call
  // the parent-class methods of the same name). For every named
  // property of every parent-class, we'll track a `Set` containing all
  // the methods that fall under that name. Any `Set` of size greater
  // than one indicates a collision.
  let propsByName = {}; // Will map property names to `Set`s
  for (let parName in parProtos) {
    
    for (let propName in parProtos[parName]) {
      
      // Now track the property `parProtos[parName][propName]` under the
      // label of `propName`
      if (!propsByName.hasOwnProperty(propName))
        propsByName[propName] = new Set();
      propsByName[propName].add(parProtos[parName][propName]);
      
    }
    
  }
  
  // For all methods defined by the child-class, create or replace the
  // entry in `propsByName` with a Set containing a single item; the
  // child-class' property at that property name (this also guarantees
  // there is no collision at this property name). Note property names
  // prefixed with "$" will be considered class properties (and the "$"
  // will be removed).
  for (let propName in properties) {
    if (propName[0] === '$') {
      
      // The "$" indicates a class property; attach to `Class`:
      Class[propName.slice(1)] = properties[propName];
      
    } else {
      
      // No "$" indicates an instance property; attach to `propsByName`:
      propsByName[propName] = new Set([ properties[propName] ]);
      
    }
  }
  
  // Ensure that "init" is defined by a parent-class or by the child:
  if (!propsByName.hasOwnProperty('init'))
    throw Error(`Class "${name}" is missing an "init" method`);
  
  // For each property name in `propsByName`, ensure that there is no
  // collision at that property name, and if there isn't, attach it to
  // the prototype! `Object.defineProperty` can ensure that prototype
  // properties won't appear during iteration with `in` keyword:
  for (let propName in propsByName) {
    let propsAtName = propsByName[propName];
    if (propsAtName.size > 1)
      throw new Error(`Class "${name}" has conflict at "${propName}"`);
    
    Object.defineProperty(Class.prototype, propName, {
      enumerable: false,
      writable: true,
      value: propsAtName.values().next().value // Get 1st item in Set
    });
  }
  
  return Class;
};

let Named = makeClass('Named', {}, () => ({
  init: function({ name }) {
    this.name = name;
  }
}));

let Running = makeClass('Running', { Named }, protos => ({
  init: function({ name, numLegs }) {
    protos.Named.init.call(this, { name });
    this.numLegs = numLegs;
  },
  run: function() {
    console.log(`${this.name} runs with ${this.numLegs} legs.`);
  }
}));

let Flying = makeClass('Flying', { Named }, protos => ({
  init: function({ name, numWings }) {
    protos.Named.init.call(this, { name });
    this.numWings = numWings;
  },
  fly: function( ){
    console.log(`${this.name} flies away with ${this.numWings} wings!`);
  }
}));

let RunningFlying = makeClass('RunningFlying', { Running, Flying }, protos => ({
  init: function({ name, numLegs, numWings }) {
    protos.Running.init.call(this, { name, numLegs });
    protos.Flying.init.call(this, { name, numWings });
  },
  takeFlight: function() {
    this.run();
    this.fly();
  }
}));

let human = new Running({ name: 'human', numLegs: 2 });
human.run();

let airplane = new Flying({ name: 'airplane', numWings: 2 });
airplane.fly();

let dragon = new RunningFlying({ name: 'dragon', numLegs: 4, numWings: 6 });
dragon.takeFlight();

makeClassফাংশন এছাড়াও বর্গ বৈশিষ্ট্য সমর্থন করে; এগুলি $প্রতীক সহ সম্পত্তি নাম উপসর্গ দ্বারা সংজ্ঞায়িত করা হয় (নোট করুন যে চূড়ান্ত সম্পত্তি নাম যে ফলাফল $মুছে ফেলা হবে)। এটি মাথায় রেখে আমরা একটি বিশেষায়িত Dragonশ্রেণি লিখতে পারি যা ড্রাগনের "ধরণের" মডেল করে, যেখানে উপলব্ধ ড্রাগনের ধরণের তালিকা ক্লাসে খোদাই করা থাকে, উদাহরণগুলির বিপরীতে:

let Dragon = makeClass('Dragon', { RunningFlying }, protos => ({

  $types: {
    wyvern: 'wyvern',
    drake: 'drake',
    hydra: 'hydra'
  },

  init: function({ name, numLegs, numWings, type }) {
    protos.RunningFlying.init.call(this, { name, numLegs, numWings });
    this.type = type;
  },
  description: function() {
    return `A ${this.type}-type dragon with ${this.numLegs} legs and ${this.numWings} wings`;
  }
}));

let dragon1 = new Dragon({ name: 'dragon1', numLegs: 2, numWings: 4, type: Dragon.types.drake });
let dragon2 = new Dragon({ name: 'dragon2', numLegs: 4, numWings: 2, type: Dragon.types.hydra });

একাধিক উত্তরাধিকারের চ্যালেঞ্জসমূহ

কোডটি makeClassনিবিড়ভাবে অনুসরণ করেছেন এমন যে কেউ উপরের কোডটি চলাকালীন নিঃশব্দে ঘটে যাওয়া একটি উল্লেখযোগ্য অনাকাঙ্ক্ষিত ঘটনাটি নোট করবেন: একটি তাত্ক্ষণিকভাবে RunningFlyingফলাফলটি Namedকনস্ট্রাক্টরের কাছে দু'বার ডাকবে !

এটি কারণ উত্তরাধিকারের গ্রাফটি দেখতে এই রকম:

 (^^ More Specialized ^^)

      RunningFlying
         /     \
        /       \
    Running   Flying
         \     /
          \   /
          Named

  (vv More Abstract vv)

যখন একটি উপ-শ্রেণীর উত্তরাধিকার গ্রাফে একই পিতাম-শ্রেণীর একাধিক পাথ থাকে ইনস্ট্যান্টেশনগুলি সেই অভিভাবক-শ্রেণীর' নির্মাতাকে একাধিকবার ডাকে।

এটির বিরুদ্ধে লড়াই করা তুচ্ছ বিষয় নয়। আসুন সরল শ্রেণীবদ্ধ সহ কয়েকটি উদাহরণ দেখি। আমরা শ্রেণি A, সর্বাধিক বিমূর্ত অভিভাবক-শ্রেণি, শ্রেণি Bএবং Cউভয়ই যে উত্তরাধিকার সূত্রে প্রাপ্ত Aএবং ক্লাস BCযা উত্তরাধিকার সূত্রে প্রাপ্ত হয়েছে Bএবং C(এবং তাই ধারণাগতভাবে "ডাবল-উত্তরাধিকারী" থেকে বিবেচনা করব A):

let A = makeClass('A', {}, () => ({
  init: function() {
    console.log('Construct A');
  }
}));
let B = makeClass('B', { A }, protos => ({
  init: function() {
    protos.A.init.call(this);
    console.log('Construct B');
  }
}));
let C = makeClass('C', { A }, protos => ({
  init: function() {
    protos.A.init.call(this);
    console.log('Construct C');
  }
}));
let BC = makeClass('BC', { B, C }, protos => ({
  init: function() {
    // Overall "Construct A" is logged twice:
    protos.B.init.call(this); // -> console.log('Construct A'); console.log('Construct B');
    protos.C.init.call(this); // -> console.log('Construct A'); console.log('Construct C');
    console.log('Construct BC');
  }
}));

আমরা যদি BCদ্বৈত-আহ্বান থেকে রোধ করতে চাই তবে আমাদের A.prototype.initউত্তরাধিকার সূত্রে প্রাপ্ত কন্ট্রাক্টরকে সরাসরি কল করার স্টাইলটি ত্যাগ করতে হবে। ডুপ্লিকেট কলগুলি ঘটছে কিনা এবং তা হওয়ার আগে শর্ট সার্কিটের পরীক্ষা করতে আমাদের কিছু স্তরের ইন্ডিয়ারেশন প্রয়োজন হবে।

আমরা বৈশিষ্ট্য ফাংশনে সরবরাহিত প্যারামিটারগুলি পরিবর্তনের বিষয়ে বিবেচনা করতে পারি: বরাবর protos, Objectউত্তরাধিকারসূত্রে প্রাপ্ত বৈশিষ্ট্যগুলি বর্ণনা করে এমন একটি কাঁচা ডেটা, আমরা উদাহরণস্বরূপ পদ্ধতিটি কল করার জন্য একটি ইউটিলিটি ফাংশনও অন্তর্ভুক্ত করতে পারি যে প্যারেন্ট পদ্ধতিগুলিও বলা হয়, তবে সদৃশ কলগুলি সনাক্ত করা হয় এবং প্রতিরোধ। আসুন আমরা এর জন্য প্যারামিটারগুলি কোথায় স্থাপন করি তা একবার দেখে নেওয়া যাক propertiesFn Function:

let makeClass = (name, parents, propertiesFn) => {

  /* ... a bunch of makeClass logic ... */

  // Allows referencing inherited functions; e.g. `parProtos.ParentClass3.usefulMethod`
  let parProtos = {};
  /* ... collect all parent methods in `parProtos` ... */

  // Utility functions for calling inherited methods:
  let util = {};
  util.invokeNoDuplicates = (instance, fnName, args, dups=new Set()) => {

    // Invoke every parent method of name `fnName` first...
    for (let parName of parProtos) {
      if (parProtos[parName].hasOwnProperty(fnName)) {
        // Our parent named `parName` defines the function named `fnName`
        let fn = parProtos[parName][fnName];

        // Check if this function has already been encountered.
        // This solves our duplicate-invocation problem!!
        if (dups.has(fn)) continue;
        dups.add(fn);

        // This is the first time this Function has been encountered.
        // Call it on `instance`, with the desired args. Make sure we
        // include `dups`, so that if the parent method invokes further
        // inherited methods we don't lose track of what functions have
        // have already been called.
        fn.call(instance, ...args, dups);
      }
    }

  };

  // Now we can call `propertiesFn` with an additional `util` param:
  // Resolve `properties` as the result of calling `propertiesFn`:
  let properties = propertiesFn(parProtos, util, Class);

  /* ... a bunch more makeClass logic ... */

};

উপরের পরিবর্তনের পুরো উদ্দেশ্যটি makeClassহ'ল যাতে propertiesFnআমরা প্রার্থনা করি তখন আমাদের কাছে অতিরিক্ত যুক্তি সরবরাহ করা হয় makeClass। আমাদের এও সচেতন হওয়া উচিত যে যে কোনও শ্রেণিতে সংজ্ঞায়িত প্রতিটি ক্রিয়াকলাপ এখন নাম অনুসারে তার সমস্তগুলির পরে একটি প্যারামিটার পেতে পারে dup, যা Setউত্তরাধিকার সূত্রে প্রাপ্ত পদ্ধতিটি কল করার ফলে ইতিমধ্যে আহ্বান করা সমস্ত ফাংশন ধারণ করে:

let A = makeClass('A', {}, () => ({
  init: function() {
    console.log('Construct A');
  }
}));
let B = makeClass('B', { A }, (protos, util) => ({
  init: function(dups) {
    util.invokeNoDuplicates(this, 'init', [ /* no args */ ], dups);
    console.log('Construct B');
  }
}));
let C = makeClass('C', { A }, (protos, util) => ({
  init: function(dups) {
    util.invokeNoDuplicates(this, 'init', [ /* no args */ ], dups);
    console.log('Construct C');
  }
}));
let BC = makeClass('BC', { B, C }, (protos, util) => ({
  init: function(dups) {
    util.invokeNoDuplicates(this, 'init', [ /* no args */ ], dups);
    console.log('Construct BC');
  }
}));

এই নতুন শৈলীটি আসলে "Construct A"একবারে একবার লগ হয় তা নিশ্চিত করতে সফল হয় যখন কোনও উদাহরণ BCশুরু হয়। তবে তিনটি ডাউনসাইড রয়েছে, তৃতীয়টি অত্যন্ত সমালোচনামূলক :

  1. এই কোডটি কম পঠনযোগ্য এবং রক্ষণাবেক্ষণযোগ্য হয়ে উঠেছে। util.invokeNoDuplicatesফাংশনটির পিছনে অনেক জটিলতা লুকিয়ে থাকে এবং এই স্টাইলটি কীভাবে বহু-আহবানকে এড়িয়ে চলে সে সম্পর্কে চিন্তাভাবনা অ-স্বজ্ঞাত এবং মাথা ব্যথাকে প্ররোচিত করে। আমাদের কাছে সেই অদ্ভুত dupsপ্যারামিটারও রয়েছে, যা ক্লাসের প্রতিটি ফাংশনে সত্যই সংজ্ঞায়িত করা দরকার । সেকি।
  2. এই কোডটি ধীরে ধীরে - একাধিক উত্তরাধিকারের সাথে কাঙ্ক্ষিত ফলাফল অর্জনের জন্য আরও কিছুটা ইন্ডিরিয়েশন এবং গণনার প্রয়োজন। দুর্ভাগ্যবশত, এই মামলাটি হতে পারে কোনো আমাদের মাল্টিপল-আবাহন সমস্যার সমাধান।
  3. সর্বাধিক উল্লেখযোগ্যভাবে, উত্তরাধিকারের উপর নির্ভরশীল ফাংশনগুলির কাঠামোটি খুব কঠোর হয়ে উঠেছে । যদি একটি উপ-শ্রেণি NiftyClassকোনও ফাংশনকে ওভাররাইড করে niftyFunctionএবং util.invokeNoDuplicates(this, 'niftyFunction', ...)সদৃশ-অনুরোধ ছাড়াই এটি চালানোর জন্য ব্যবহার করে, তবে প্রতিটি পিতামাতা শ্রেণীর NiftyClass.prototype.niftyFunctionনাম চিহ্নিত ফাংশনটিকে niftyFunctionএটি সংজ্ঞায়িত করবে, those শ্রেণি থেকে কোনও প্রত্যাবর্তন মান উপেক্ষা করবে এবং অবশেষে এর বিশেষায়িত যুক্তি সম্পাদন করবে NiftyClass.prototype.niftyFunction। এটিই সম্ভব সম্ভাব্য কাঠামো । যদি NiftyClassউত্তরাধিকারসূত্রে হয় CoolClassএবং GoodClassএবং এই উভয় পিতাম-শ্রেণি niftyFunctionতাদের নিজস্ব সংজ্ঞা সরবরাহ করে NiftyClass.prototype.niftyFunctionতবে কখনই (একাধিক প্রার্থনার ঝুঁকি ছাড়াই) সক্ষম হতে পারবে না:
    • উ:NiftyClass প্রথমে বিশেষায়িত যুক্তি চালান , তারপরে পিতা-মাতার শ্রেণীর বিশেষ যুক্তি যুক্ত করুন
    • বি। সমস্ত বিশেষায়িত প্যারেন্ট যুক্তি শেষ হওয়ার পরেNiftyClass অন্য যে কোনও সময়ে বিশেষায়িত যুক্তি চালান
    • সি তার পিতামাতার বিশেষ যুক্তির ফিরে আসার মানের উপর নির্ভর করে শর্তাধীন আচরণ করুন
    • ডি চলুন একটি নির্দিষ্ট পিতা বা মাতা চলমান বিশেষ হচ্ছে niftyFunctionপুরাপুরি

অবশ্যই, আমরা নীচে বিশেষ ফাংশনগুলি সংজ্ঞায়িত করে উপরে প্রতিটি বর্ণিত সমস্যা সমাধান করতে পারি util:

  • উ: সংজ্ঞায়িতutil.invokeNoDuplicatesSubClassLogicFirst(instance, fnName, ...)
  • বি। সংজ্ঞায়িত করুন util.invokeNoDuplicatesSubClassAfterParent(parentName, instance, fnName, ...)( parentNameপিতা-মাতার নাম কোথায় যেখানে বিশেষায়িত যুক্তি তাত্ক্ষণিকভাবে শিশু-শ্রেণীর বিশেষায়িত যুক্তি অনুসরণ করবে)
  • সি। সংজ্ঞায়িত করুন util.invokeNoDuplicatesCanShortCircuitOnParent(parentName, testFn, instance, fnName, ...)(এই ক্ষেত্রে testFnঅভিভাবকের নামকরণের জন্য বিশেষ যুক্তির ফলাফল প্রাপ্ত parentNameহবে true/falseএবং সংক্ষিপ্ত সার্কিটটি ঘটবে কিনা তা নির্দেশ করে একটি মূল্য ফেরত দেবে )
  • ডি সংজ্ঞায়িত util.invokeNoDuplicatesBlackListedParents(blackList, instance, fnName, ...)(এই ক্ষেত্রে blackListএকটি হবে Arrayপিতা বা মাতা নাম যার বিশেষ যুক্তিবিজ্ঞান পুরাপুরি এড়ানো করা উচিত)

এই সমাধানগুলি সমস্ত উপলভ্য, তবে এটি মোট বিপর্যয় ! উত্তরাধিকার সূত্রে ফাংশন কল গ্রহণ করতে পারে এমন প্রতিটি অনন্য কাঠামোর জন্য আমাদের অধীনে একটি বিশেষ পদ্ধতি প্রয়োজন util। কি পরম দুর্যোগ।

এটি মাথায় রেখে আমরা ভাল একাধিক উত্তরাধিকার বাস্তবায়নের চ্যালেঞ্জগুলি দেখতে শুরু করতে পারি। makeClassআমি এই উত্তরের প্রদত্ত সম্পূর্ণ বাস্তবায়ন এমনকি একাধিক-আহবান সমস্যা, বা একাধিক উত্তরাধিকার সম্পর্কিত উত্পন্ন অন্যান্য অনেক সমস্যাও বিবেচনা করে না।

এই উত্তরটি খুব দীর্ঘ হচ্ছে। আমি আশা করি makeClassআমার অন্তর্ভুক্ত করা বাস্তবায়ন এখনও নিখুঁত না হলেও কার্যকর হবে। আমি আরও আশা করি যে এই বিষয়ে আগ্রহী কেউ আরও পড়ার সাথে সাথে মনে রাখার জন্য আরও প্রসঙ্গ অর্জন করেছে!


0

প্যাকেজটি দেখুন আইইউনিট

আইইউনিটিতে বাস্তবায়িত ধারণা সংমিশ্রণটি আপনি বেশ গতিশীল উপায়ে যা খুঁজছেন তা সরবরাহ করে।


0

কনস্ট্রাক্টর ফাংশন ব্যবহার করে প্রোটোটাইপ শৃঙ্খলার উদাহরণ এখানে :

function Lifeform () {             // 1st Constructor function
    this.isLifeform = true;
}

function Animal () {               // 2nd Constructor function
    this.isAnimal = true;
}
Animal.prototype = new Lifeform(); // Animal is a lifeform

function Mammal () {               // 3rd Constructor function
    this.isMammal = true;
}
Mammal.prototype = new Animal();   // Mammal is an animal

function Cat (species) {           // 4th Constructor function
    this.isCat = true;
    this.species = species
}
Cat.prototype = new Mammal();     // Cat is a mammal

এই ধারণাটি জাভাস্ক্রিপ্টের জন্য "ক্লাস" এর ইয়েহুদা কাটজের সংজ্ঞা ব্যবহার করেছে:

... একটি জাভাস্ক্রিপ্ট "ক্লাস" হ'ল একটি ফাংশন অবজেক্ট যা কনস্ট্রাক্টর প্লাস সংযুক্ত প্রোটোটাইপ অবজেক্ট হিসাবে কাজ করে। ( সূত্র: গুরু কাটজ )

অবজেক্ট.ক্রিয়েট পদ্ধতির বিপরীতে , যখন ক্লাসগুলি এভাবে নির্মিত হয় এবং আমরা একটি "শ্রেণি" এর উদাহরণ তৈরি করতে চাই, আমাদের "শ্রেণি" কীসের উত্তরাধিকার সূত্রে প্রাপ্ত তা আমাদের জানতে হবে না। আমরা শুধু ব্যবহার new

// Make an instance object of the Cat "Class"
var tiger = new Cat("tiger");

console.log(tiger.isCat, tiger.isMammal, tiger.isAnimal, tiger.isLifeform);
// Outputs: true true true true

অগ্রগতির ক্রমটি বোঝা উচিত। প্রথমে এটি ইনস্ট্যান্স অবজেক্টে দেখায়, তারপরে এটি প্রোটোটাইপ, তারপরে পরবর্তী প্রোটোটাইপ ইত্যাদি

// Let's say we have another instance, a special alien cat
var alienCat = new Cat("alien");
// We can define a property for the instance object and that will take 
// precendence over the value in the Mammal class (down the chain)
alienCat.isMammal = false;
// OR maybe all cats are mutated to be non-mammals
Cat.prototype.isMammal = false;
console.log(alienCat);

আমরা প্রোটোটাইপগুলিও সংশোধন করতে পারি যা ক্লাসে নির্মিত সমস্ত বস্তুর প্রভাব ফেলবে।

// All cats are mutated to be non-mammals
Cat.prototype.isMammal = false;
console.log(tiger, alienCat);

আমি মূলত এই উত্তরটি দিয়ে কিছু লিখেছিলাম ।


2
ওপি একাধিক প্রোটোটাইপ চেইনের জন্য অনুরোধ করছে (উদাহরণস্বরূপ এবং এর childউত্তরাধিকার সূত্রে ) আপনার উদাহরণটি কেবল একটি শৃঙ্খলা সম্পর্কে কথা বলে। parent1parent2
poshest

0

দৃশ্যের একজন প্রয়াত হলেন সরলডেক্লেয়ার । যাইহোক, একাধিক উত্তরাধিকার নিয়ে কাজ করার সময়, আপনি এখনও মূল নির্মাতাদের অনুলিপিগুলি সহ শেষ করবেন। এটি জাভাস্ক্রিপ্টে একটি প্রয়োজনীয়তা ...

Merc।


এটি জাভাস্ক্রিপ্টে একটি প্রয়োজনীয়তা ... ইএস 6 প্রক্সি না হওয়া পর্যন্ত।
জোনাথন

প্রক্সিগুলি আকর্ষণীয়! আমি স্পষ্টতই সিম্পলডেক্লেয়ার পরিবর্তন করে দেখব যাতে প্রক্সিগুলি যখন তারা স্ট্যান্ডার্ডের অংশ হয়ে যায় তখন তাদের ব্যবহার করার পদ্ধতিগুলি অনুলিপি করার প্রয়োজন হয় না। SimpleDeclare এর কোড পড়া এবং পরিবর্তনের সত্যিই, সত্যিই সহজ ...
Merc

0

আমি ds.oop ব্যবহার করব । এটি প্রোটোটাইপ.জেএস এবং অন্যদের মতো। একাধিক উত্তরাধিকার খুব সহজ করে তোলে এবং এর ন্যূনতম। (মাত্র 2 বা 3 কেবি) এছাড়াও ইন্টারফেস এবং নির্ভরতা ইনজেকশন যেমন কিছু অন্যান্য ঝরঝরে বৈশিষ্ট্য সমর্থন করে

/*** multiple inheritance example ***********************************/

var Runner = ds.class({
    run: function() { console.log('I am running...'); }
});

var Walker = ds.class({
    walk: function() { console.log('I am walking...'); }
});

var Person = ds.class({
    inherits: [Runner, Walker],
    eat: function() { console.log('I am eating...'); }
});

var person = new Person();

person.run();
person.walk();
person.eat();

0

এটি সম্পর্কে, এটি জাভাস্ক্রিপ্টে একাধিক উত্তরাধিকার প্রয়োগ করে:

    class Car {
        constructor(brand) {
            this.carname = brand;
        }
        show() {
            return 'I have a ' + this.carname;
        }
    }

    class Asset {
        constructor(price) {
            this.price = price;
        }
        show() {
            return 'its estimated price is ' + this.price;
        }
    }

    class Model_i1 {        // extends Car and Asset (just a comment for ourselves)
        //
        constructor(brand, price, usefulness) {
            specialize_with(this, new Car(brand));
            specialize_with(this, new Asset(price));
            this.usefulness = usefulness;
        }
        show() {
            return Car.prototype.show.call(this) + ", " + Asset.prototype.show.call(this) + ", Model_i1";
        }
    }

    mycar = new Model_i1("Ford Mustang", "$100K", 16);
    document.getElementById("demo").innerHTML = mycar.show();

এবং এখানে বিশেষায়িত_যুক্ত () ইউটিলিটি ফাংশনের কোড রয়েছে:

function specialize_with(o, S) { for (var prop in S) { o[prop] = S[prop]; } }

এটি বাস্তব কোড যা চলে। আপনি এটি এইচটিএমএল ফাইলে কপি-পেস্ট করতে পারেন এবং নিজে চেষ্টা করে দেখতে পারেন। এটা কাজ করে।

এটি জাভাস্ক্রিপ্টে এমআই বাস্তবায়নের প্রচেষ্টা। কোডের বেশি নয়, আরও জানার উপায়।

দয়া করে এ সম্পর্কে আমার সম্পূর্ণ নিবন্ধটি নির্দ্বিধায় দেখুন, https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS


0

আমি অন্যের বৈশিষ্ট্যগুলিতে আমার কী ক্লাসগুলির প্রয়োজন তা সরিয়ে দিয়েছি এবং তাদের পছন্দ করে এমন স্বয়ংক্রিয় পয়েন্টে একটি প্রক্সি যুক্ত করেছি:

class A {
    constructor()
    {
        this.test = "a test";
    }

    method()
    {
        console.log("in the method");
    }
}

class B {
    constructor()
    {
        this.extends = [new A()];

        return new Proxy(this, {
            get: function(obj, prop) {

                if(prop in obj)
                    return obj[prop];

                let response = obj.extends.find(function (extended) {
                if(prop in extended)
                    return extended[prop];
            });

            return response ? response[prop] : Reflect.get(...arguments);
            },

        })
    }
}

let b = new B();
b.test ;// "a test";
b.method(); // in the method
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.