জাভাস্ক্রিপ্টের প্রোটোটাইপ-ভিত্তিক উত্তরাধিকারের ভাল উদাহরণ


89

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


4
আপনি কি সেই বেস লাইব্রেরিটি পরীক্ষা করার সুযোগ পেয়েছেন? এটি সত্যিই দুর্দান্ত, এবং খুব ছোট। আপনি যদি এটি পছন্দ করেন তবে আমার উত্তরটিকে উত্তর হিসাবে চিহ্নিত করার বিষয়টি বিবেচনা করুন। টিআইএ, রোল্যান্ড
রোল্যান্ড বোম্যান

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

উত্তর:


48

জাভাস্ক্রিপ্ট প্রোটোটাইপাল উত্তরাধিকারে ডগলাস ক্রকফোর্ডের একটি সুন্দর পৃষ্ঠা রয়েছে :

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

ডিন এডওয়ার্ডের বেস.জেএস , মটুলস ক্লাস বা জন রেসিগের সাধারণ উত্তরাধিকারের কাজগুলি জাভাস্ক্রিপ্টে শাস্ত্রীয় উত্তরাধিকার করার উপায় ।


newObj = Object.create(oldObj);আপনি কেবল শ্রেণি-মুক্ত চাইলে কেন এটি করবেন না ? অন্যথায়, oldObjনির্মাণকারী ফাংশনের প্রোটোটাইপ অবজেক্টের সাথে প্রতিস্থাপনের কাজ করা উচিত?
সাইকেল 21

76

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

// Declaring our Animal object
var Animal = function () {

    this.name = 'unknown';

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

    return this;
};

// Declaring our Dog object
var Dog = function () {

    // A private variable here        
    var private = 42;

    // overriding the name
    this.name = "Bello";

    // Implementing ".bark()"
    this.bark = function () {
        return 'MEOW';
    }  

    return this;
};


// Dog extends animal
Dog.prototype = new Animal();

// -- Done declaring --

// Creating an instance of Dog.
var dog = new Dog();

// Proving our case
console.log(
    "Is dog an instance of Dog? ", dog instanceof Dog, "\n",
    "Is dog an instance of Animal? ", dog instanceof Animal, "\n",
    dog.bark() +"\n", // Should be: "MEOW"
    dog.getName() +"\n", // Should be: "Bello"
    dog.private +"\n" // Should be: 'undefined'
);

তবে এই পদ্ধতির সমস্যাটি হ'ল এটি প্রতিবার তৈরি করার পরে এটি পুনরায় তৈরি করবে। আর একটি পদ্ধতি হ'ল প্রোটোটাইপ স্ট্যাকগুলিতে আপনার অবজেক্টগুলি ঘোষণা করা:

// Defining test one, prototypal
var testOne = function () {};
testOne.prototype = (function () {
    var me = {}, privateVariable = 42;
    me.someMethod = function () {
        return privateVariable;
    };

    me.publicVariable = "foo bar";
    me.anotherMethod = function () {
        return this.publicVariable;
    };

    return me;

}());


// Defining test two, function
var testTwo = ​function() {
    var me = {}, privateVariable = 42;
    me.someMethod = function () {
        return privateVariable;
    };

    me.publicVariable = "foo bar";
    me.anotherMethod = function () {
        return this.publicVariable;
    };

    return me;
};


// Proving that both techniques are functionally identical
var resultTestOne = new testOne(),
    resultTestTwo = new testTwo();

console.log(
    resultTestOne.someMethod(), // Should print 42
    resultTestOne.publicVariable // Should print "foo bar"
);

console.log(
    resultTestTwo.someMethod(), // Should print 42
    resultTestTwo.publicVariable // Should print "foo bar"
);



// Performance benchmark start
var stop, start, loopCount = 1000000;

// Running testOne
start = (new Date()).getTime(); 
for (var i = loopCount; i>0; i--) {
    new testOne();
}
stop = (new Date()).getTime();

console.log('Test one took: '+ Math.round(((stop/1000) - (start/1000))*1000) +' milliseconds');



// Running testTwo
start = (new Date()).getTime(); 
for (var i = loopCount; i>0; i--) {
    new testTwo();
}
stop = (new Date()).getTime();

console.log('Test two took: '+ Math.round(((stop/1000) - (start/1000))*1000) +' milliseconds');

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


4
নোট যে কি testOne মধ্যে privateVariableকেবল পরিধি একটি পরিবর্তনশীল IIFE , এবং সমস্ত উদাহরণ জুড়ে তার ভাগ, তাই আপনি এটা উদাহরণস্বরূপ-নির্দিষ্ট ডেটা জমা করা উচিত নয়। (টেস্টটিতে এটি দুটি উদাহরণ হিসাবে নির্দিষ্ট, যেমন টেস্টটুতে প্রতিটি কল দুটি () প্রতিটি নতুন, প্রতি-সুযোগ, সুযোগ তৈরি করে)
শেসেক

আমি উত্সাহিত করেছি কারণ আপনি অন্য পদ্ধতিটি দেখিয়েছেন এবং কেন এটি ব্যবহার করবেন না কারণ এটি অনুলিপিগুলি তৈরি করেছে
মারফি 316

প্রতিবার অবজেক্টটি পুনরায় তৈরি করার সমস্যাটি মূলত প্রতিটি নতুন বস্তুর জন্য তৈরি পদ্ধতিগুলির কারণে। তবে আমরা পদ্ধতিটি চালু করে সমস্যাটি প্রশমিত করতে পারি Dog.prototype। সুতরাং পরিবর্তে ব্যবহার this.bark = function () {...}না করে , আমরা ফাংশন Dot.prototype.bark = function () {...}বাইরে করতে পারেন Dog। ( এই উত্তরের আরও বিশদ দেখুন )
সি হুয়াং

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

// 1. Explicitly call base (Shape) constructor from subclass (Circle) constructor passing this as the explicit receiver
function Circle(x, y, r) {
    Shape.call(this, x, y);
    this.r = r;
}

// 2. Use Object.create to construct the subclass prototype object to avoid calling the base constructor
Circle.prototype = Object.create(Shape.prototype);

4
সম্ভবত আপনার উত্তরের সাথে এই লিঙ্কটি যুক্ত করা ছবিটি আরও সম্পূর্ণ করতে পারে: developer.mozilla.org/en/docs/Web/JavaScript/References/…
ডায়নম

14

আমি YUI এবং ডিন এডওয়ার্ডের Baseলাইব্রেরিতে একবার দেখে নেব : http://dean.edwards.name/weblog/2006/03/base/

YUI এর জন্য আপনি ল্যাং মডিউলটি একবার দেখে নিতে পারেন , esp। YAHOO.lang.extend পদ্ধতি। এবং তারপরে, আপনি কিছু উইজেট বা ইউটিলিটিগুলির উত্স ব্রাউজ করতে পারেন এবং তারা কীভাবে সেই পদ্ধতিটি ব্যবহার করে তা দেখতে পারেন।


YUI 2 কে ২০১১ সালের হিসাবে অবমূল্যায়ন করা হয়েছে, সুতরাং লিঙ্কটি langআধা-ভাঙা। YUI 3 এর জন্য কেউ এটি ঠিক করার জন্য যত্নশীল?
ack

ল্যাং ইন ইয়ু 3 এর কোনও বর্ধিত পদ্ধতি নেই বলে মনে হচ্ছে। তবে যেহেতু উত্তরটি উদাহরণ হিসাবে বাস্তবায়নটি ব্যবহার করতে চাইছে সংস্করণটি কোনও ব্যাপার নয়।
eMBee

5

মাইক্রোসফ্টের এএসপি.এনইটি আজাক্স গ্রন্থাগার, http://www.asp.net/ajax/ রয়েছে

পাশাপাশি আশেপাশে প্রচুর ভাল এমএসডিএন নিবন্ধ রয়েছে, যার মধ্যে অবজেক্ট-ওরিয়েন্টেড কৌশলগুলি সহ অ্যাডভান্সড ওয়েব অ্যাপ্লিকেশন তৈরি করা রয়েছে ।


5

এটি মিক্সির নোড বই ( http://book.mixu.net/node/ch6.html ) থেকে আমি স্পষ্ট উদাহরণ খুঁজে পেয়েছি :

আমি উত্তরাধিকারের তুলনায় রচনাটির পক্ষে:

রচনা - কোনও বস্তুর কার্যকারিতা অন্যান্য শ্রেণীর সামগ্রীর সমন্বয়ে অন্যান্য অবজেক্টের উদাহরণ দিয়ে তৈরি হয়। উত্তরাধিকার - কোনও বস্তুর কার্যকারিতা তার নিজস্ব কার্যকারিতা এবং এর প্যারেন্ট ক্লাস থেকে কার্যকারিতা নিয়ে গঠিত। আপনার যদি উত্তরাধিকার থাকতে হবে তবে সাধারণ পুরানো জেএস ব্যবহার করুন

যদি আপনাকে উত্তরাধিকার বাস্তবায়ন করতে হয় তবে কমপক্ষে অন্য একটি মানহীন বাস্তবায়ন / যাদু ফাংশনটি এড়িয়ে চলুন। খাঁটি ES3- এ আপনি উত্তরাধিকারের যুক্তিসঙ্গত ফ্যাসিমিল কীভাবে বাস্তবায়ন করতে পারেন তা এখানে রয়েছে (যতক্ষণ না আপনি প্রোটোটাইপগুলিতে সম্পত্তি নির্দিষ্ট না করার নিয়মটি অনুসরণ করেন):

function Animal(name) {
  this.name = name;
};
Animal.prototype.move = function(meters) {
  console.log(this.name+" moved "+meters+"m.");
};

function Snake() {
  Animal.apply(this, Array.prototype.slice.call(arguments));
};
Snake.prototype = new Animal();
Snake.prototype.move = function() {
  console.log("Slithering...");
  Animal.prototype.move.call(this, 5);
};

var sam = new Snake("Sammy the Python");
sam.move();

এটি শাস্ত্রীয় উত্তরাধিকার হিসাবে একই জিনিস নয় - তবে এটি স্ট্যান্ডার্ড, বোধগম্য জাভাস্ক্রিপ্ট এবং এতে কার্যত কার্যকারিতা রয়েছে যা লোকেরা বেশিরভাগ ক্ষেত্রে সন্ধান করে: চেইনেবল কনস্ট্রাক্টর এবং সুপারক্লাসের পদ্ধতিগুলি কল করার ক্ষমতা।


4

ES6 classএবংextends

ES6 classএবং extendsপূর্বের সম্ভাব্য প্রোটোটাইপ চেইন ম্যানিপুলেশনের জন্য কেবল সিনট্যাক্স চিনির, এবং তত যুক্তিযুক্তভাবে সর্বাধিক ক্যানোনিকাল সেটআপ।

প্রথমে প্রোটোটাইপ চেইন এবং .সম্পত্তি অনুসন্ধান সম্পর্কে আরও জানুন : https://stackoverflow.com/a/23877420/895245

এখন যা ঘটে তা ডিকনস্ট্রাক্ট করা যাক:

class C {
    constructor(i) {
        this.i = i
    }
    inc() {
        return this.i + 1
    }
}

class D extends C {
    constructor(i) {
        super(i)
    }
    inc2() {
        return this.i + 2
    }
}
// Inheritance syntax works as expected.
(new C(1)).inc() === 2
(new D(1)).inc() === 2
(new D(1)).inc2() === 3
// "Classes" are just function objects.
C.constructor === Function
C.__proto__ === Function.prototype
D.constructor === Function
// D is a function "indirectly" through the chain.
D.__proto__ === C
D.__proto__.__proto__ === Function.prototype
// "extends" sets up the prototype chain so that base class
// lookups will work as expected
var d = new D(1)
d.__proto__ === D.prototype
D.prototype.__proto__ === C.prototype
// This is what `d.inc` actually does.
d.__proto__.__proto__.inc === C.prototype.inc
// Class variables
// No ES6 syntax sugar apparently:
// /programming/22528967/es6-class-variable-alternatives
C.c = 1
C.c === 1
// Because `D.__proto__ === C`.
D.c === 1
// Nothing makes this work.
d.c === undefined

সমস্ত পূর্বনির্ধারিত অবজেক্ট ছাড়া সরলীকৃত চিত্র:

      __proto__
(C)<---------------(D)         (d)
| |                |           |
| |                |           |
| |prototype       |prototype  |__proto__
| |                |           |
| |                |           |
| |                | +---------+
| |                | |
| |                | |
| |                v v
|__proto__        (D.prototype)
| |                |
| |                |
| |                |__proto__
| |                |
| |                |
| | +--------------+
| | |
| | |
| v v
| (C.prototype)--->(inc)
|
v
Function.prototype


1

আমি যে সেরা উদাহরণগুলি দেখেছি তা হ'ল ডগলাস ক্রকফোর্ডের জাভাস্ক্রিপ্ট: গুড পার্টস । ভাষার প্রতি ভারসাম্যপূর্ণ দৃষ্টিভঙ্গি পেতে আপনাকে সহায়তা করার জন্য এটি অবশ্যই মূল্যবান।

ডগলাস ক্রকফোর্ড জেএসএন ফরমেটের জন্য দায়বদ্ধ এবং ইয়াহুতে জাভাস্ক্রিপ্ট গুরু হিসাবে কাজ করেন।


7
দায়বদ্ধ? এটি প্রায় "দোষী" বলে মনে হচ্ছে :)
রোল্যান্ড বোম্যান

@ রোল্যান্ড আমার কাছে মনে হয় যে ডেটা সংরক্ষণের জন্য জেএসএন হ'ল একটি দুর্দান্ত অ-ভার্বোজ বিন্যাস। তিনি অবশ্যই এটি আবিষ্কার করেন নি, যদিও ফর্ম্যাটটি ছিল 2002 সালে স্টিমের কনফিগারেশন সেটিংসের জন্য
ক্রিস এস

ক্রিস এস, আমারও তাই মনে হয় - আরও অনেক সময় আমি আশা করি আমরা সবাই এক্সএমএলকে এক্সচেঞ্জ ফর্ম্যাট হিসাবে এড়িয়ে যেতে পারতাম এবং এখনই জেএসএন-তে চলে যেতে পারতাম।
রোল্যান্ড বোম্যান

4
উদ্ভাবনের মতো খুব বেশি কিছু নয়: জেএসএন হ'ল জাভাস্ক্রিপ্টের নিজস্ব অবজেক্ট লিটারাল সিনট্যাক্সের একটি উপসেট যা প্রায় ১৯৯ 1997 সাল থেকে ভাষায় রয়েছে
টিম ডাউন

@ টাইম ভাল পয়েন্ট - আমি বুঝতে পারিনি যে এটি শুরু থেকেই আছে
ক্রিস এস

0

ECMAScript সংস্করণ নির্দিষ্ট প্রয়োগের সাথে একটি স্নিপেট জাভাস্ক্রিপ্ট প্রোটোটাইপ-ভিত্তিক উত্তরাধিকার রয়েছে। এটি বর্তমান রানটাইম অনুযায়ী ES6, ES5 এবং ES3 বাস্তবায়নের মধ্যে কোনটি ব্যবহার করবে তা স্বয়ংক্রিয়ভাবে চয়ন করবে।


0

জাভাস্ক্রিপ্টে প্রোটোটাইপ ভিত্তিক উত্তরাধিকারের উদাহরণ যুক্ত করা।

// Animal Class
function Animal (name, energy) {
  this.name = name;
  this.energy = energy;
}

Animal.prototype.eat = function (amount) {
  console.log(this.name, "eating. Energy level: ", this.energy);
  this.energy += amount;
  console.log(this.name, "completed eating. Energy level: ", this.energy);
}

Animal.prototype.sleep = function (length) {
  console.log(this.name, "sleeping. Energy level: ", this.energy);
  this.energy -= 1;
  console.log(this.name, "completed sleeping. Energy level: ", this.energy);
}

Animal.prototype.play = function (length) {
  console.log(this.name, " playing. Energy level: ", this.energy);
  this.energy -= length;
  console.log(this.name, "completed playing. Energy level: ", this.energy);
}

// Dog Class
function Dog (name, energy, breed) {
  Animal.call(this, name, energy);
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function () {
  console.log(this.name, "barking. Energy level: ", this.energy);
  this.energy -= 1;
  console.log(this.name, "done barking. Energy level: ", this.energy);
}

Dog.prototype.showBreed = function () {
  console.log(this.name,"'s breed is ", this.breed);
}

// Cat Class
function Cat (name, energy, male) {
  Animal.call(this, name, energy);
  this.male = male;
}

Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;

Cat.prototype.meow = function () {
  console.log(this.name, "meowing. Energy level: ", this.energy);
  this.energy -= 1;
  console.log(this.name, "done meowing. Energy level: ", this.energy);
}

Cat.prototype.showGender = function () {
  if (this.male) {
    console.log(this.name, "is male.");
  } else {
    console.log(this.name, "is female.");
  }
}

// Instances
const charlie = new Dog("Charlie", 10, "Labrador");
charlie.bark();
charlie.showBreed();

const penny = new Cat("Penny", 8, false);
penny.meow();
penny.showGender();

ES6 কনস্ট্রাক্টর এবং সুপার কীওয়ার্ডগুলির ব্যবহার হিসাবে উত্তরাধিকারের তুলনায় আরও সহজ বাস্তবায়ন ব্যবহার করে।

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