প্রোটোটাইপ কনস্ট্রাক্টর সেট করা কেন প্রয়োজন?


294

ইন MDN প্রবন্ধে উত্তরাধিকার সম্পর্কে অধ্যায় ভিত্তিক জাভাস্ক্রিপ্ট অবজেক্ট পরিচিতি , আমি লক্ষ্য করেছি তারা prototype.constructor সেট করুন:

// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;  

এটি কি কোনও গুরুত্বপূর্ণ উদ্দেশ্য করে? এটাকে বাদ দেওয়া কি ঠিক?


23
আপনি এই জিজ্ঞাসা করে খুশি হলেন: আমি গতকাল একই ডকুমেন্টেশন পড়েছি এবং নির্মাতাকে সুস্পষ্টভাবে সেট করার পিছনে যুক্তি সম্পর্কে আগ্রহী ছিলাম।
Wylie

6
আমি কেবল এটি উল্লেখ করতে হবে, এই প্রশ্নটি এখন আপনি লিখিত নিবন্ধে সংযুক্ত!
মেরি

7
কিছুই প্রয়োজন নেই
অযৌক্তিকভাবে

1
subclass.prototype.constructorনির্দেশ করবে parent_classযদি তোমরা লিখুন না subclass.prototype.constructor = subclass; এটি হ'ল subclass.prototype.constructor()সরাসরি ব্যবহার করলে অপ্রত্যাশিত ফলাফল আসবে।
কুয়ানইউ চু

উত্তর:


263

এটি সর্বদা প্রয়োজনীয় নয়, তবে এর ব্যবহারও রয়েছে। মনে করুন আমরা বেস Personশ্রেণিতে একটি অনুলিপি পদ্ধতি তৈরি করতে চেয়েছিলাম । এটার মত:

// define the Person Class  
function Person(name) {
    this.name = name;
}  

Person.prototype.copy = function() {  
    // return new Person(this.name); // just as bad
    return new this.constructor(this.name);
};  

// define the Student class  
function Student(name) {  
    Person.call(this, name);
}  

// inherit Person  
Student.prototype = Object.create(Person.prototype);

এখন যখন আমরা একটি নতুন তৈরি করি Studentএবং এটি অনুলিপি করি তখন কী হয় ?

var student1 = new Student("trinth");  
console.log(student1.copy() instanceof Student); // => false

অনুলিপি এর উদাহরণ নয় Student। এটি কারণ (সুস্পষ্ট চেক ব্যতীত), আমাদের Studentকাছে "বেস" শ্রেণি থেকে কোনও অনুলিপি ফেরানোর উপায় নেই । আমরা শুধুমাত্র একটি ফিরে আসতে পারেন Person। তবে, আমরা যদি কনস্ট্রাক্টরটিকে রিসেট করে থাকি:

// correct the constructor pointer because it points to Person  
Student.prototype.constructor = Student;

... তারপরে সবকিছু প্রত্যাশার মতো কাজ করে:

var student1 = new Student("trinth");  
console.log(student1.copy() instanceof Student); // => true

34
দ্রষ্টব্য: constructorগুণাবলীটির জেএসে কোনও বিশেষ অর্থ নেই, তাই আপনি এটিও ডাকতে পারেন bananashake। পার্থক্য কেবলমাত্র যখনই আপনি কোনও ফাংশন ঘোষণা করেন ইঞ্জিনটি স্বয়ংক্রিয়ভাবে শুরু constructorহয় । তবে এটি যে কোনও সময় ওভাররাইট করা যেতে পারে। f.prototypef
ব্যবহারকারী 123444555621

58
@ Pumbaa80 - আমি আপনার পয়েন্ট, কিন্তু এটা সত্য যে ইঞ্জিন স্বয়ংক্রিয়ভাবে সূচনা পেতে constructorমাধ্যম এটা যে নেই , প্রায় কাছাকাছি সংজ্ঞা দ্বারা জাতীয় বিশেষ অর্থ আছে।
ওয়েইন

13
আমি কেবল এটি স্পষ্ট করে বলতে চাই যে আপনি যে আচরণটি বলেছিলেন তার কারণ আপনি তার return new this.constructor(this.name);পরিবর্তে ব্যবহার করছেন return new Person(this.name);। যেহেতু this.constructorহয় Studentফাংশন (কারণ আপনি এটি দিয়ে সেট Student.prototype.constructor = Student;), copyফাংশন কলিং শেষ পর্যন্ত Studentফাংশন। //just as badমন্তব্যটি নিয়ে আপনার উদ্দেশ্য কী ছিল তা আমি নিশ্চিত নই ।
সিইজিআরডি

12
@lwburk "// ঠিক ততটা খারাপ" বলতে কী বোঝ?
সিইজিআরডি

6
আমি মনে করি এটি পেয়েছি। কিন্তু, কি যদি Student: কন্সট্রাকটর মত একটি অতিরিক্ত যুক্তি যোগ করেছিলেন Student(name, id)? তারপরে কী আমাদের copyফাংশনটি ওভাররাইড করতে Personহবে, এর মধ্যে থেকে সংস্করণটি কল করা এবং তারপরে অতিরিক্ত idসম্পত্তি অনুলিপি করতে হবে ?
স্ন্যাপফ্র্যাক্টলপপ

76

এটি কি কোনও গুরুত্বপূর্ণ উদ্দেশ্য করে?

হ্যা এবং না.

ইএস 5 এবং এর আগে, জাভাস্ক্রিপ্ট নিজেই constructorকোনও কিছুর জন্য ব্যবহার করেনি । এটি সংজ্ঞায়িত করেছে যে কোনও ফাংশনের prototypeসম্পত্তির ডিফল্ট অবজেক্টটিতে এটি থাকবে এবং এটি ফাংশনটির পুনরায় উল্লেখ করবে এবং এটি ছিল । স্পেসিফিকেশন অন্য কিছুই এটিকে উল্লেখ করা হয় না।

এটি ES2015 (ES6) এ পরিবর্তিত হয়েছে, যা উত্তরাধিকারের শ্রেণিবিন্যাসের সাথে এটি ব্যবহার শুরু করে। উদাহরণস্বরূপ, প্রত্যাবর্তনের নতুন প্রতিশ্রুতি তৈরি করার সময় আপনি যে প্রতিশ্রুতিতে কল করেছেন ( স্পাইসিস কনস্ট্রাক্টরের মাধ্যমে ) Promise#thenতার constructorসম্পত্তি ব্যবহার করে । এটি অ্যারে সাব টাইপিংয়ের সাথেও জড়িত ( অ্যারেস্পেসেসক্রিয়েটের মাধ্যমে ) )।

ভাষার বাইরে, কখনও কখনও লোকেরা জেনেরিক "ক্লোন" ফাংশনগুলি তৈরি করার চেষ্টা করার সময় বা যখন সাধারণত তারা বিশ্বাস করত যে বিষয়টি অবজেক্টের কনস্ট্রাক্টর ফাংশন হবে তা উল্লেখ করতে চাইলে এটি ব্যবহার করত। আমার অভিজ্ঞতা হ'ল এটি ব্যবহার বিরল, তবে কখনও কখনও লোকেরা এটি ব্যবহার করে।

এটাকে বাদ দেওয়া কি ঠিক?

এটি ডিফল্টরূপে সেখানে রয়েছে, যখন আপনি কোনও ফাংশনের সম্পত্তিতে বস্তুটি প্রতিস্থাপন করবেন কেবল তখনই এটি ফিরিয়ে আনতে হবে prototype:

Student.prototype = Object.create(Person.prototype);

আপনি যদি এটি না করেন:

Student.prototype.constructor = Student;

... তাহলে Student.prototype.constructorউত্তরাধিকার সূত্রে প্রাপ্ত Person.prototypeযা থেকে (সম্ভবত) constructor = Person। সুতরাং এটি বিভ্রান্তিকর। এবং অবশ্যই, যদি আপনি এমন কিছু উপশৃঙ্খলা তৈরি করে যা এটি ব্যবহার করে (যেমন Promiseবা Array) এবং class¹ (যা এটি আপনার জন্য পরিচালনা করে) না ব্যবহার করে তবে আপনি এটি সঠিকভাবে সেট করেছেন তা নিশ্চিত করতে চাইবেন। সুতরাং মূলত: এটি একটি ভাল ধারণা।

আপনার কোডে (বা আপনি ব্যবহার করেন এমন লাইব্রেরি কোড) কোনওটি ব্যবহার না করে তা ঠিক আছে। আমি সর্বদা নিশ্চিত করেছি যে এটি সঠিকভাবে ওয়্যার্ড হয়েছিল।

অবশ্যই, ES2015 (ওরফে ES6) এর classকীওয়ার্ড সহ, বেশিরভাগ সময় আমরা এটি ব্যবহার করতাম, আমাদের আর দরকার হয় না, কারণ এটি করার সময় এটি আমাদের জন্য পরিচালিত হয়

class Student extends Person {
}

¹ "... আপনি যে এটি ব্যবহার করে (ভালো কিছু subclassing করছি Promiseবা Array) এবং ব্যবহার class..."  - এটা সম্ভব যে কাজ করতে, কিন্তু এটা একটি বাস্তব ব্যথা (এবং একটি বিট নিরীহ)। আপনি ব্যবহার করতে হবে Reflect.construct


12

TLDR; অতি প্রয়োজনীয় নয়, তবে সম্ভবত এটি দীর্ঘমেয়াদে সহায়তা করবে এবং এটি করা আরও সঠিক।

দ্রষ্টব্য: আমার পূর্ববর্তী উত্তরটি বিভ্রান্তিকরভাবে লেখা হয়েছিল বলে অনেকগুলি সম্পাদনা করা হয়েছিল এবং এর কিছু ত্রুটি ছিল যা উত্তর দেওয়ার জন্য আমার ভিড়তে আমি মিস করি। যারা কিছু গুরুতর ত্রুটি চিহ্নিত করেছেন তাদের ধন্যবাদ।

মূলত, এটি জাভাস্ক্রিপ্টে সঠিকভাবে সাবক্লাসিংয়ের তারে রয়েছে। যখন আমরা সাবক্লাস করি তখন প্রোটোটাইপাল প্রতিনিধি কোনও prototypeবস্তুর ওভাররাইটিং সহ সঠিকভাবে কাজ করে তা নিশ্চিত করার জন্য আমাদের কয়েকটি মজার জিনিস করতে হবে । একটি prototypeবস্তুকে ওভাররাইটিংয়ে অন্তর্ভুক্ত রয়েছেconstructor , সুতরাং আমাদের তখন রেফারেন্সটি ঠিক করতে হবে।

ES5- এ 'ক্লাস' কীভাবে কাজ করে তা দ্রুত তাড়াতাড়ি চলুন।

ধরা যাক আপনার একটি কনস্ট্রাক্টর ফাংশন এবং এর প্রোটোটাইপ রয়েছে:

//Constructor Function
var Person = function(name, age) {
  this.name = name;
  this.age = age;
}

//Prototype Object - shared between all instances of Person
Person.prototype = {
  species: 'human',
}

আপনি যখন কনস্ট্রাক্টরকে তাত্ক্ষণিকভাবে ডাকবেন, তখন বলুন Adam:

// instantiate using the 'new' keyword
var adam = new Person('Adam', 19);

newশব্দ 'যে ব্যক্তি' দিয়ে প্রার্থনা মূলত কোডের কয়েকটি অতিরিক্ত লাইন ব্যক্তি কন্সট্রাকটর চালানো হবে:

function Person (name, age) {
  // This additional line is automatically added by the keyword 'new'
  // it sets up the relationship between the instance and the prototype object
  // So that the instance will delegate to the Prototype object
  this = Object.create(Person.prototype);

  this.name = name;
  this.age = age;

  return this;
}

/* So 'adam' will be an object that looks like this:
 * {
 *   name: 'Adam',
 *   age: 19
 * }
 */

যদি আমরা console.log(adam.species), adamদৃষ্টান্তটি অনুসন্ধান ব্যর্থ হবে এবং এর প্রোটোটাইপাল চেইনটি অনুসন্ধান করবে .prototypeযা এটিPerson.prototype - এবং Person.prototype এর একটি .speciesসম্পত্তি আছে, তাই অনুসন্ধান সফল হবে Person.prototype। এটি তখন লগ হবে'human'

এখানে, Person.prototype.constructorউইল সঠিকভাবে নির্দেশ করবে Person

তাই এখন আকর্ষণীয় অংশ, তথাকথিত 'সাবক্লাসিং'। আমরা যদি কোনও Studentশ্রেণি তৈরি করতে চাই , এটি Personকিছু অতিরিক্ত পরিবর্তন সহ ক্লাসের একটি উপশ্রেণী , আমাদের নিশ্চিত করতে হবে যে Student.prototype.constructorযথাযথতার জন্য শিক্ষার্থীর দিকে পয়েন্টগুলি।

এটি নিজে থেকে এটি করে না। আপনি যখন সাবক্লাস করেন, কোডটি এর মতো দেখায়:

var Student = function(name, age, school) {
 // Calls the 'super' class, as every student is an instance of a Person
 Person.call(this, name, age);
 // This is what makes the Student instances different
 this.school = school
}

var eve = new Student('Eve', 20, 'UCSF');

console.log(Student.prototype); // this will be an empty object: {}

new Student()এখানে কল করা আমাদের কাছে থাকা সমস্ত বৈশিষ্ট্যের সাথে একটি বস্তু ফিরে আসবে। এখানে, যদি আমরা পরীক্ষা eve instanceof Personকরি তবে এটি ফিরে আসবেfalse । আমরা যদি অ্যাক্সেস করার চেষ্টা eve.speciesকরি তবে এটি ফিরে আসবেundefined

অন্য কথায়, আমাদের প্রতিনিধিদলকে ওয়্যার আপ করতে হবে যাতে eve instanceof Personসত্যটি ফিরে আসে এবং Studentডেলিগেটের উদাহরণগুলি সঠিকভাবে প্রতিপন্ন হয়Student.prototype এবং তারপরেPerson.prototype

তবে যেহেতু আমরা এটিকে newকীওয়ার্ড দিয়ে ডাকছি, সেই আহ্বানটি কী যুক্ত করে তা মনে রাখবেন? এটা তোলে কল করবে Object.create(Student.prototype), যা আমরা কীভাবে মধ্যে যে delegational সম্পর্ক স্থাপন Studentএবং Student.prototype। এই মুহূর্তে নোট করুন, Student.prototypeখালি। সুতরাং এটির .speciesউদাহরণস্বরূপ অনুসন্ধান করা Studentব্যর্থ হবে কারণ এটি কেবলমাত্র প্রতিনিধি হিসাবে উপস্থিত হয় Student.prototype, এবং.species সম্পত্তি উপস্থিত না Student.prototype

আমরা যখন বরাদ্দ করবো Student.prototypeথেকে Object.create(Person.prototype), Student.prototypeনিজেই তারপর প্রতিনিধিদের Person.prototypeএবং আপ খুঁজছেন eve.speciesফিরে আসবে humanযেমন আমরা আশা। সম্ভবত আমরা এটি স্টুডেন্ট.প্রোটোটাইপ এবং পার্সন.প্রোটোটাইপ থেকে উত্তরাধিকার সূত্রে পেতে চাই। সুতরাং আমাদের এটি সব ঠিক করা প্রয়োজন।

/* This sets up the prototypal delegation correctly 
 *so that if a lookup fails on Student.prototype, it would delegate to Person's .prototype
 *This also allows us to add more things to Student.prototype 
 *that Person.prototype may not have
 *So now a failed lookup on an instance of Student 
 *will first look at Student.prototype, 
 *and failing that, go to Person.prototype (and failing /that/, where do we think it'll go?)
*/
Student.prototype = Object.create(Person.prototype);

এখন প্রতিনিধি কাজ করে তবে আমরা Student.prototypeএকটি দিয়ে ওভাররাইট করছি Person.prototype। সুতরাং আমরা যদি কল Student.prototype.constructor, এটি Personপরিবর্তে নির্দেশ করবে Studentএই কারণে আমরা এটি ঠিক করার প্রয়োজন হয়।

// Now we fix what the .constructor property is pointing to    
Student.prototype.constructor = Student

// If we check instanceof here
console.log(eve instanceof Person) // true

ইএস 5-তে, আমাদের constructorসম্পত্তিটি এমন একটি রেফারেন্স যা কোনও ফাংশনকে বোঝায় যা আমরা 'কনস্ট্রাক্টর' হওয়ার অভিপ্রায় নিয়ে লিখেছি। newকীওয়ার্ড আমাদের যা দেয় তা বাদ দিয়ে কনস্ট্রাক্টর অন্যথায় একটি 'প্লেইন' ফাংশন।

ES6- এ, constructorএখন আমরা ক্লাসগুলি লেখার পদ্ধতিতে তৈরি করা হয়েছে - যেমনটি, যখন আমরা কোনও ক্লাস ঘোষণা করি তখন এটি একটি পদ্ধতি হিসাবে সরবরাহ করা হয়। এটি কেবল সিনট্যাকটিক চিনি তবে এটি আমাদের superবিদ্যমান ক্লাসটি প্রসারিত করার সময় অ্যাক্সেসের মতো কিছু সুযোগসুবিধা দেয় । সুতরাং আমরা উপরের কোডটি এভাবে লিখব:

class Person {
  // constructor function here
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  // static getter instead of a static property
  static get species() {
    return 'human';
  }
}

class Student extends Person {
   constructor(name, age, school) {
      // calling the superclass constructor
      super(name, age);
      this.school = school;
   }
}

eve instanceof Studentফিরে এসেছি true। ব্যাখ্যার জন্য stackoverflow.com/questions/35537995/… দেখুন । এছাড়াও আপনি যখন বলছেন আপনি which is, at the moment, nothingকি উল্লেখ করছেন? প্রতিটি ফাংশনের একটি প্রোটোটাইপ থাকে তাই যদি আমি Student.prototypeএটি পরীক্ষা করি তবে এটি কিছু।
অসীম বানসাল

আমার ভুল. এটি 'ব্যক্তিত্বের আগের উদাহরণ' পড়া উচিত ছিল যা মিথ্যা ফিরে আসবে। আমি সেই অংশটি সংশোধন করব। আপনি সঠিক যে প্রতিটি ফাংশনে একটি প্রোটোটাইপ সম্পত্তি রয়েছে। যাইহোক , প্রোটোটাইপ বরাদ্দ না করে Object.create(Person.prototype), Student.prototypeখালি। সুতরাং আমরা যদি লগইন করি তবে eve.speciesএটি তার সুপারক্লাস, ব্যক্তি হিসাবে সঠিকভাবে অর্পণ করবে না এবং এটি লগ হবে না 'human'। সম্ভবত, আমরা চাই প্রতিটি উপক্লাস তার প্রোটোটাইপ এবং এর সুপারের প্রোটোটাইপ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হোক।
bthehuman

স্পষ্ট করে which is, at the moment, nothingবলতে গেলে, আমি বোঝাতে চাইছিলাম যে Student.prototypeঅবজেক্টটি খালি।
bthehuman

প্রোটোটাইপ আরও: এর নিয়োগ ছাড়া Student.prototypeকরার Object.create(Person.prototype)- যা, যদি আপনি প্রত্যাহার, একই ভাবে পারসন সমস্ত উদাহরণ আপ প্রতিনিধি করতে নির্ধারণ করা হয় Person.prototypeএকটি দৃষ্টান্ত একটি সম্পত্তি আপ খুঁজছেন - Studentযাতে দায়িত্বপ্রাপ্ত হবে শুধুমাত্র Student.prototype । সুতরাং eve.speciesএটির অনুসন্ধান ব্যর্থ হবে। যদি আমরা এটি নির্ধারণ করি, তবে Student.prototypeনিজেই এটি প্রতিনিধি হয়ে যায় Person.prototypeএবং সন্ধান করে eve.speciesফিরে আসবে human
bthehuman

এখানে বেশ কয়েকটি জিনিস ভুল আছে বলে মনে হচ্ছে: "আপনি যখন 'সাবক্লাসিং' অনুকরণ করার চেষ্টা করছেন তখন এটি প্রয়োজনীয় হয় [...] যাতে আপনি যখন কোনও উদাহরণ instance'সাবক্লাস' নির্মাণকারী কিনা তা পরীক্ষা করে নিলে তা সঠিক হবে" " না, instanceofব্যবহার করবেন না constructor"তবে, আমরা যদি শিক্ষার্থীর .প্রোটোটাইপ কনস্ট্রাক্টর অনুসন্ধান করি তবে এটি ব্যক্তির দিকে ইঙ্গিত করবে" না, এটি হবে Student। আমি এই উদাহরণের বিন্দু বুঝতে পারি না। কনস্ট্রাক্টরে কোনও ফাংশন কল করা উত্তরাধিকার নয়। "ES6 এ, কনস্ট্রাক্টর এখন কোনও ফাংশনের রেফারেন্সের পরিবর্তে একটি আসল ফাংশন" আহ কি?
ফেলিক্স ক্লিং

10

আমি একমত না প্রোটোটাইপ সেট করা প্রয়োজন হয় না। ঠিক একই কোডটি নিন তবে প্রোটোটাইপ.কমস্ট্রাক্টর লাইনটি সরিয়ে দিন। কিছু পরিবর্তন হয়? না। এখন, নিম্নলিখিত পরিবর্তনগুলি করুন:

Person = function () {
    this.favoriteColor = 'black';
}

Student = function () {
    Person.call(this);
    this.favoriteColor = 'blue';
}

এবং পরীক্ষার কোড শেষে ...

alert(student1.favoriteColor);

রঙ নীল হবে।

আমার অভিজ্ঞতায় প্রোটোটাইপ কনস্ট্রাক্টরের পরিবর্তন, আপনি খুব নির্দিষ্ট, খুব জটিল জিনিসগুলি না করাই বেশি কিছু করেন না যা সম্ভবত যেভাবে ভাল অনুশীলন নয় :)

সম্পাদনা: কিছুটা জন্য ওয়েবে চারপাশে ঝাঁকুনির পরে এবং কিছু পরীক্ষা-নিরীক্ষা করার পরে, দেখে মনে হচ্ছে লোকে নির্মাণকারীকে সেট করেছে যাতে এটি 'নতুন' দিয়ে তৈরি করা জিনিসটির মতো 'দেখতে' লাগে। আমি অনুমান করি যে আমি তর্ক করব যে এর সাথে সমস্যা হ'ল জাভাস্ক্রিপ্ট একটি প্রোটোটাইপ ভাষা - উত্তরাধিকার হিসাবে এমন কোনও জিনিস নেই। তবে বেশিরভাগ প্রোগ্রামার প্রোগ্রামিংয়ের পটভূমি থেকে আসে যা উত্তরাধিকারকে 'উপায়' হিসাবে ঠেলে দেয়। সুতরাং আমরা এই প্রোটোটাইপিক ভাষাকে একটি 'ক্লাসিক' ভাষা .. যেমন 'ক্লাস' বাড়ানোর মতো চেষ্টা করার এবং তৈরি করার জন্য বিভিন্ন ধরণের জিনিস নিয়ে হাজির। সত্যই, তারা যে উদাহরণ দিয়েছে, একটি নতুন শিক্ষার্থী একজন ব্যক্তি - এটি অন্য শিক্ষার্থীর কাছ থেকে 'বাড়ানো' হয় না .. শিক্ষার্থী সমস্ত ব্যক্তি সম্পর্কে, এবং যে ব্যক্তি শিক্ষার্থী সে তাও। ছাত্র এবং আপনি যাই হোক না কেন প্রসারিত করুন

ক্রকফোর্ড কিছুটা ক্রেজি এবং অতিমাত্রায় alous


8
এটি প্রোটোটাইপ চেইনের উত্তরাধিকারী হয় না।
সাইফার

1
@ সাইফার ধীর তালি চার বছর পরে কথোপকথনে স্বাগত জানায়। হ্যাঁ, প্রোটোটাইপ শৃঙ্খল হয় উত্তরাধিকারসূত্রে, যেখানে আপনি prototype.constructor ওভাররাইট নির্বিশেষে। এটি পরীক্ষা করে দেখুন।
স্টিফেন

7
প্রোটোটাইপের উত্তরাধিকারসূত্রে প্রাপ্ত কোডটি আপনি হারিয়েছেন। ইন্টারনেটে স্বাগতম
সাইফার

1
লিঙ্কযুক্ত নিবন্ধের কোডের ভিত্তিতে সাইফার কোড স্নিপেট ছিল। প্রশ্নটি সম্পূর্ণরূপে পড়তে আপনাকে স্বাগতম। উহু. অপেক্ষা করুন।
স্টিফেন

1
@ মাচার আমি এটিকে শাস্ত্রীয় উত্তরাধিকার হিসাবে বুঝিয়েছি। আমার দিক থেকে শব্দবন্ধের পছন্দ কম।
স্টিফেন

9

এটি একটি বিশাল ক্ষতি আছে যে আপনি যদি লিখেন

Student.prototype.constructor = Student;

তবে তারপরে যদি এমন কোনও শিক্ষক থাকতেন যার প্রোটোটাইপটি ব্যক্তিও ছিল এবং আপনি লিখেছিলেন

Teacher.prototype.constructor = Teacher;

তাহলে স্টুডেন্ট কনস্ট্রাক্টর এখন শিক্ষক!

সম্পাদনা: আপনি মোজিলার উদাহরণ হিসাবে Object.create ব্যবহার করে তৈরি করা ব্যক্তি শ্রেণীর নতুন উদাহরণ ব্যবহার করে শিক্ষার্থী এবং শিক্ষক প্রোটোটাইপগুলি সেট করেছিলেন তা নিশ্চিত করে আপনি এড়াতে পারবেন।

Student.prototype = Object.create(Person.prototype);
Teacher.prototype = Object.create(Person.prototype);

1
Student.prototype = Object.create(...)এই প্রশ্নে ধরে নেওয়া হয়। এই উত্তরটি সম্ভাব্য বিভ্রান্তি ছাড়া আর কিছুই যুক্ত করে না।
আন্ড্রে চেল্লা

3
@ অ্যান্ড্রিনিউজ আমি এই উত্তরটি সহায়ক বলে মনে করেছি। Object.create(...)এমডিএন নিবন্ধে ব্যবহার করা হয় যা প্রশ্ন উত্সাহিত করেছে, তবে নিজেই প্রশ্নটিতে নয়। আমি নিশ্চিত যে অনেক লোক ক্লিক করে না।
অ্যালেক্স রস

প্রশ্নে উল্লিখিত লিঙ্কযুক্ত নিবন্ধটি Object.create () ব্যবহার করে। এই উত্তরটি এবং সম্পাদনাটি উত্তরটি সত্যই প্রাসঙ্গিক নয় এবং এটি কমপক্ষে বলতে বিভ্রান্ত করছে :-)
ড্রেনাই

1
বিস্তৃত বিষয় হ'ল এমন গ্যাটাচগুলি রয়েছে যা জাভাস্ক্রিপ্ট প্রোটোটাইপগুলিতে নতুন লোককে ছিনিয়ে নেবে। যদি আমরা 2016 সালে আলোচনা করছি তবে আপনার অবশ্যই সত্যিকারের ES6 ক্লাস, ব্যাবেল এবং / অথবা টাইপস্ক্রিপ্ট ব্যবহার করা উচিত। তবে আপনি যদি সত্যই এভাবে ম্যানুয়ালি ক্লাসগুলি বানাতে চান তবে এটি বুঝতে সাহায্য করে যে প্রোটোটাইপ চেইনগুলি তাদের শক্তি উত্সাহিত করতে সত্যিই কীভাবে কাজ করে। আপনি কোনও বিষয়টিকে প্রোটোটাইপ হিসাবে ব্যবহার করতে পারেন এবং সম্ভবত আপনি কোনও পৃথক অবজেক্ট নতুন করতে চান না। তদ্ব্যতীত, এইচটিএমএল 5 সম্পূর্ণরূপে বিস্তৃত হওয়ার আগে, অবজেক্ট.প্রেইট সর্বদা উপলব্ধ ছিল না, সুতরাং ভুলভাবে কোনও শ্রেণি স্থাপন করা সহজ ছিল।
জেমস ডি

5

এখনও পর্যন্ত বিভ্রান্তি আছে।

আসল উদাহরণ অনুসরণ করে আপনার student1যেমন বিদ্যমান অবজেক্টটি রয়েছে :

var student1 = new Student("Janet", "Applied Physics");

মনে করুন আপনি কীভাবে student1তৈরি হয় তা জানতে চান না , আপনি কেবল এটির মতো অন্য একটি জিনিস চান, আপনি এর student1মতো নির্মাণকারী সম্পত্তি ব্যবহার করতে পারেন :

var student2 = new student1.constructor("Mark", "Object-Oriented JavaScript");

Studentকনস্ট্রাক্টর সম্পত্তি সেট না করা থাকলে এটি এখানে থেকে সম্পত্তি পেতে ব্যর্থ হবে । বরং এটি একটি Personঅবজেক্ট তৈরি করবে ।


2

প্রোটোটাইপ কনস্ট্রাক্টর সেট করা কেন সত্যই প্রয়োজন তার একটি দুর্দান্ত কোড উদাহরণ পেয়ে গেলেন ..

function CarFactory(name){ 
   this.name=name;  
} 
CarFactory.prototype.CreateNewCar = function(){ 
    return new this.constructor("New Car "+ this.name); 
} 
CarFactory.prototype.toString=function(){ 
    return 'Car Factory ' + this.name;
} 

AudiFactory.prototype = new CarFactory();      // Here's where the inheritance occurs 
AudiFactory.prototype.constructor=AudiFactory;       // Otherwise instances of Audi would have a constructor of Car 

function AudiFactory(name){ 
    this.name=name;
} 

AudiFactory.prototype.toString=function(){ 
    return 'Audi Factory ' + this.name;
} 

var myAudiFactory = new AudiFactory('');
  alert('Hay your new ' + myAudiFactory + ' is ready.. Start Producing new audi cars !!! ');            

var newCar =  myAudiFactory.CreateNewCar(); // calls a method inherited from CarFactory 
alert(newCar); 

/*
Without resetting prototype constructor back to instance, new cars will not come from New Audi factory, Instead it will come from car factory ( base class )..   Dont we want our new car from Audi factory ???? 
*/

আপনার createNewCarপদ্ধতি কারখানা তৈরি করছে !? এছাড়াও এটি দেখে মনে হচ্ছে var audiFactory = new CarFactory("Audi")উত্তরাধিকার ব্যবহারের চেয়ে এটি ব্যবহার করা উচিত ছিল।
বার্গি

আপনার উদাহরণ this.constructorঅভ্যন্তরীণভাবে ব্যবহার করছে , সুতরাং এটি সেট করতে হবে তাই অবাক হওয়ার কিছু নেই। এটি ছাড়া আপনার কোনও উদাহরণ আছে?
দিমিত্রি জইতসেভ

1

এই দিনগুলিতে সুগারড ফাংশন 'ক্লাস' বা 'নতুন' ব্যবহারের দরকার নেই। বস্তুর আক্ষরিক ব্যবহার করুন।

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

const Person = {
  name: '[Person.name]',
  greeting: function() {
    console.log( `My name is ${ this.name || '[Name not assigned]' }` );
  }
};
// Person.greeting = function() {...} // or define outside the obj if you must

// Object.create version
const john = Object.create( Person );
john.name = 'John';
console.log( john.name ); // John
john.greeting(); // My name is John 
// Define new greeting method
john.greeting = function() {
    console.log( `Hi, my name is ${ this.name }` )
};
john.greeting(); // Hi, my name is John

// Object.assign version
const jane = Object.assign( Person, { name: 'Jane' } );
console.log( jane.name ); // Jane
// Original greeting
jane.greeting(); // My name is Jane 

// Original Person obj is unaffected
console.log( Person.name ); // [Person.name]
console.log( Person.greeting() ); // My name is [Person.name]

এটি একটি পড়ার মূল্য :

শ্রেণিভিত্তিক অবজেক্ট-ভিত্তিক ভাষা যেমন জাভা এবং সি ++ দুটি পৃথক পৃথক সত্তার ধারণার ভিত্তিতে প্রতিষ্ঠিত: শ্রেণি এবং দৃষ্টান্ত ances

...

একটি প্রোটোটাইপ-ভিত্তিক ভাষা, যেমন জাভাস্ক্রিপ্ট, এই পার্থক্য তৈরি করে না: এতে কেবল অবজেক্ট থাকে। একটি প্রোটোটাইপ-ভিত্তিক ভাষার প্রোটোটাইপিকাল অবজেক্টের ধারণা থাকে, এটি একটি টেম্পলেট হিসাবে ব্যবহৃত হয় যা থেকে কোনও নতুন অবজেক্টের প্রাথমিক বৈশিষ্ট্য পাওয়া যায়। যে কোনও অবজেক্ট তার নিজস্ব বৈশিষ্ট্য নির্দিষ্ট করে দিতে পারে, আপনি এটি তৈরির সময় বা রান সময়ে। তদ্ব্যতীত, যে কোনও বস্তু দ্বিতীয় বস্তুর প্রথম বস্তুর বৈশিষ্ট্য ভাগ করে নেওয়ার সুযোগ দিয়ে অন্য কোনও অবজেক্টের প্রোটোটাইপ হিসাবে যুক্ত হতে পারে


1

আপনার যখন toStringবানরকিপাচিং ছাড়াই বিকল্পের প্রয়োজন হয় তখন এটি প্রয়োজনীয়:

//Local
foo = [];
foo.toUpperCase = String(foo).toUpperCase;
foo.push("a");
foo.toUpperCase();

//Global
foo = [];
window.toUpperCase = function (obj) {return String(obj).toUpperCase();}
foo.push("a");
toUpperCase(foo);

//Prototype
foo = [];
Array.prototype.toUpperCase = String.prototype.toUpperCase;
foo.push("a");
foo.toUpperCase();

//toString alternative via Prototype constructor
foo = [];
Array.prototype.constructor = String.prototype.toUpperCase;
foo.push("a,b");
foo.constructor();

//toString override
var foo = [];
foo.push("a");
var bar = String(foo);
foo.toString = function() { return bar.toUpperCase(); }
foo.toString();

//Object prototype as a function
Math.prototype = function(char){return Math.prototype[char]};
Math.prototype.constructor = function() 
  {
  var i = 0, unicode = {}, zero_padding = "0000", max = 9999;
  
  while (i < max) 
    {
    Math.prototype[String.fromCharCode(parseInt(i, 16))] = ("u" + zero_padding + i).substr(-4);

    i = i + 1;
    }    
  }

Math.prototype.constructor();
console.log(Math.prototype("a") );
console.log(Math.prototype["a"] );
console.log(Math.prototype("a") === Math.prototype["a"]);


এর মধ্যে কোনটি করার কথা? foo.constructor()??
রাই-

0

সম্পাদনা, আমি আসলে ভুল ছিল। লাইন আউট মন্তব্য করা একেবারে এর আচরণ পরিবর্তন করে না। (আমি এটি পরীক্ষা করেছি)


হ্যাঁ, এটি প্রয়োজনীয়। যখন তুমি কর

Student.prototype = new Person();  

Student.prototype.constructorহয়ে Person। অতএব, কলিং Student()দ্বারা নির্মিত একটি বস্তু ফিরে আসবে Person। আপনি যদি তারপর না

Student.prototype.constructor = Student; 

Student.prototype.constructorপুনরায় সেট করা হয় Student। এখন যখন আপনি Student()একে এক্সিকিউটস Studentকল করেন, যা প্যারেন্ট কন্সট্রাক্টরকে কল করে Parent(), এটি সঠিকভাবে উত্তরাধিকার সূত্রে প্রাপ্ত বস্তুটি দেয়। যদি আপনি Student.prototype.constructorকল করার আগে পুনরায় সেট না করেন তবে আপনি এমন একটি জিনিস পাবেন যাতে কোনও বৈশিষ্ট্য সেট করা থাকবে না Student()


3
প্রোটোটাইপ কাঠামো কোনও ব্যক্তি হতে পারে তবে এটি উপযুক্ত কারণ এটি ব্যক্তি থেকে সমস্ত সম্পত্তি এবং পদ্ধতি উত্তরাধিকার সূত্রে প্রাপ্ত। প্রোটোটাইপ.কমস্ট্রাক্টর সেট না করেই নতুন স্টুডেন্ট () তৈরি করা তার নিজস্ব কনস্ট্রাক্টরকে যথাযথভাবে কল করে।
স্টিফেন

0

সাধারণ কন্সট্রাক্টর ফাংশন দেওয়া হয়েছে:

function Person(){
    this.name = 'test';
}


console.log(Person.prototype.constructor) // function Person(){...}

Person.prototype = { //constructor in this case is Object
    sayName: function(){
        return this.name;
    }
}

var person = new Person();
console.log(person instanceof Person); //true
console.log(person.sayName()); //test
console.log(Person.prototype.constructor) // function Object(){...}

ডিফল্টরূপে ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/References/Global_Objects/Object/constructor থেকে স্পেসিফিকেশন ), সমস্ত প্রোটোটাইপগুলি স্বয়ংক্রিয়ভাবে কনস্ট্রাক্টর নামে একটি সম্পত্তি পেয়ে যায় যা ফাংশনে ফিরে আসে points যা এটি একটি সম্পত্তি। কনস্ট্রাক্টরের উপর নির্ভর করে অন্যান্য বৈশিষ্ট্য এবং পদ্ধতিগুলি প্রোটোটাইপে যুক্ত হতে পারে যা খুব সাধারণ অনুশীলন নয় তবে তবুও এটি এক্সটেনশনের জন্য অনুমোদিত।

সুতরাং কেবল উত্তর: আমাদের নিশ্চিত করা দরকার যে প্রোটোটাইপ.কমস্ট্রাক্টরের মানটি সঠিকভাবে সেট করা আছে যেমনটি স্পেসিফিকেশন বলে মনে করা হয়।

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


0

এখানে MDN এর একটি উদাহরণ যা এর ব্যবহারগুলি বুঝতে আমি খুব সহায়ক বলে মনে করেছি।

জাভাস্ক্রিপ্টে, আমাদের রয়েছে async functionsযা AsyncFunction অবজেক্টটি প্রদান করে। AsyncFunctionগ্লোবাল অবজেক্ট নয় তবে কেউ constructorসম্পত্তি ব্যবহার করে এটি ব্যবহার করতে পারে।

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

// AsyncFunction constructor
var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor

var a = new AsyncFunction('a', 
                          'b', 
                          'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);');

a(10, 20).then(v => {
  console.log(v); // prints 30 after 4 seconds
});

-1

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

Student.prototype.constructor = Student; 

না, আপনার কাছে এখনকার "কনস্ট্রাক্টর" এর একটি উল্লেখ রয়েছে।

ওয়েনের উত্তরে, এটিকে সঠিক হিসাবে চিহ্নিত করা হয়েছে, আপনি নীচের কোডটি ঠিক একই জিনিস করতে পারেন

Person.prototype.copy = function() {  
    // return new Person(this.name); // just as bad
    return new this.constructor(this.name);
};  

নীচের কোড সহ (কেবল এই ব্যক্তির সাথে এই কনস্ট্রাক্টর প্রতিস্থাপন)

Person.prototype.copy = function() {  
    // return new Person(this.name); // just as bad
    return new Person(this.name);
}; 

Godশ্বরের ধন্যবাদ যে ES6 সহ ধ্রুপদী উত্তরাধিকার বিশোধকরা ভাষাটির স্থানীয় অপারেটরগুলিকে ক্লাস, প্রসারিত এবং সুপারের মতো ব্যবহার করতে পারেন এবং আমাদের প্রোটোটাইপ.কমস্ট্রাক্টর সংশোধন এবং পিতামাতার রেফারেন্সের মতো দেখতে হবে না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.