জাভাস্ক্রিপ্ট প্রোটোটাইপ ব্যবহার করে কল করার পদ্ধতি


129

জাভাস্ক্রিপ্টে একটি প্রোটোটাইপ পদ্ধতি থেকে বেস পদ্ধতিটি কল করা সম্ভব যদি এটি ওভাররাইড হয়ে যায়?

MyClass = function(name){
    this.name = name;
    this.do = function() {
        //do somthing 
    }
};

MyClass.prototype.do = function() {  
    if (this.name === 'something') {
        //do something new
    } else {
        //CALL BASE METHOD
    }
};

বেস পদ্ধতিটি কোনটি? this.do = ফাংশন () const the কনস্ট্রাক্টরে?
আয়নু জি স্টান

উত্তর:


200

আপনি ঠিক কী করার চেষ্টা করছেন তা আমি বুঝতে পারি নি, তবে সাধারণত এই রেখাগুলিতে অবজেক্ট-নির্দিষ্ট আচরণটি করা হয়:

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

MyClass.prototype.doStuff = function() {
    // generic behaviour
}

var myObj = new MyClass('foo');

var myObjSpecial = new MyClass('bar');
myObjSpecial.doStuff = function() {
    // do specialised stuff
    // how to call the generic implementation:
    MyClass.prototype.doStuff.call(this /*, args...*/);
}

1
আমি এটি পাই না, আমি মার্কভিপিসি হিসাবে একই উদ্দেশ্যে এখানে এসেছি। মানে, আমি একধরনের "ব্যক্তিগত" পদ্ধতি চাই যা প্রোটোটাইপের অন্যান্য পদ্ধতি থেকে ব্যবহৃত হয়। আপনার প্রতিক্রিয়া আমাকে একটি কারখানা তৈরি করতে বাধ্য করেছে এবং এটি এড়াতে কোনও উপায় আছে কিনা তা আমি জানতে চাই।
R01010010

10
জেএস-তে "শ্রেণি" শব্দ ব্যবহার করবেন না কারণ এটি বিভ্রান্তি সৃষ্টি করে। জাভাস্ক্রিপ্টে কোনও ক্লাস নেই
পোলারিস

1
এটি কেবল তাত্ক্ষণিকৃত বস্তুর জন্য কাজ করে। আপনি যদি সমস্ত দৃষ্টান্ত ওভাররাইড করতে চান?
সুপারটনস্কি

আমার জন্য কাজ কর! ঠিক আমার যা প্রয়োজন ছিল। আমার 4 জন কনস্ট্রাক্টর রয়েছে যা পিতামাতার কাছ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত। তাদের মধ্যে দু'জনকে ভিত্তি নির্মাণকারীকে ওভাররাইড করে একটি পদ্ধতি কল করতে হবে যা তাদের প্রোটোটাইপ। এই আমাকে ঠিক যে অনুমতি দেয়।
বাইনারিগিয়ান্ট

3
আমি বুঝতে পারি না কেন এটিতে এতগুলি উত্সাহ রয়েছে এবং এটি সঠিক হিসাবে চিহ্নিত হয়েছে। এটি কেবল বেস-শ্রেণীর এক উদাহরণের জন্য আচরণকে ওভাররাইড করে, উপ-শ্রেণীর সমস্ত উদাহরণ নয়। সুতরাং এটি প্রশ্নের উত্তর দেয় না।
ব্লুরাজা - ড্যানি প্লেফুঘুফুট

24

এটি করার একটি উপায় হ'ল বেস পদ্ধতিটি সংরক্ষণ করা এবং তারপরে ওভাররডেন পদ্ধতি থেকে এটিকে কল করা

MyClass.prototype._do_base = MyClass.prototype.do;
MyClass.prototype.do = function(){  

    if (this.name === 'something'){

        //do something new

    }else{
        return this._do_base();
    }

};

11
এটি অসীম পুনরাবৃত্তি তৈরি করবে।
জোহান টিডন

3
আমি সেখানে ছিলাম: অসীম পুনরাবৃত্তি।
jperelli

অন্য ধারাটি _do_base কল করে চলছে এবং এটি প্রোটোটাইপ.ডোর একটি উল্লেখ reference যেহেতু কোনও প্যারামিটার (বা রাষ্ট্র) পরিবর্তিত হয়নি, তাই কোডটি আবার _do_base এ কল করে অন্যটিতে চলে যাবে।
জোহান টিডন

10
@ জোহান টিডন স্টোরের _do_baseআগে যা যা কার্য নির্ধারণ করা হয়েছিল তার একটি রেফারেন্স সঞ্চয় করে। যদি কিছুই না থাকত, তবে তা হত undefined। জাভাস্ক্রিপ্ট makeএক্সপ্রেশনস নয় যেহেতু আপনি পরামর্শ মতো সেগুলি কখনই অলসভাবে মূল্যায়ন করা হয় না। এখন, যদি প্রোটোটাইপ উত্তরাধিকার সূত্রে প্রাপ্ত হয় তবে এটি _O_base যা মনে করে তা এটির বেস টাইপের বাস্তবায়ন হিসাবে সংরক্ষণ করার জন্য ব্যবহৃত হয় do, তবে আপনার সমস্যা আছে। সুতরাং, হ্যাঁ, এই পদ্ধতিটি ব্যবহার করা হলে আসল ফাংশন প্রয়োগের রেফারেন্সটি সংরক্ষণ করার জন্য একটি বন্ধন হ'ল উত্তম, উত্তরাধিকার-নিরাপদ উপায় — যদিও এটি ব্যবহারের প্রয়োজন Function.prototype.call(this)
বিনকি

16

আমি ভয় করি যে আপনার উদাহরণটি আপনার ধারণা মতো কাজ করে না। এই অংশ:

this.do = function(){ /*do something*/ };

সংজ্ঞাটি ওভাররাইট করে

MyClass.prototype.do = function(){ /*do something else*/ };

যেহেতু সদ্য নির্মিত বস্তুর ইতিমধ্যে একটি "কর" সম্পত্তি রয়েছে তাই এটি প্রোটোটাইপাল চেইনটি সন্ধান করে না।

জাভাস্ক্রিপ্টে উত্তরাধিকারের ধ্রুপদী ফর্মটি অবাস্তব এবং উপলব্ধি করা শক্ত। আমি এর পরিবর্তে ডগলাস ক্রকফোর্ডগুলি সহজ উত্তরাধিকারের ধরণটি ব্যবহার করার পরামর্শ দেব। এটার মত:

function my_class(name) {
    return {
        name: name,
        do: function () { /* do something */ }
    };
}

function my_child(name) {
    var me = my_class(name);
    var base_do = me.do;
    me.do = function () {
        if (this.name === 'something'){
            //do something new
        } else {
            base_do.call(me);
        }
    }
    return me;
}

var o = my_child("something");
o.do(); // does something new

var u = my_child("something else");
u.do(); // uses base function

আমার মতে জাভাস্ক্রিপ্টে অবজেক্টস, কনস্ট্রাক্টর এবং উত্তরাধিকার পরিচালনা করার একটি আরও পরিষ্কার উপায়। আপনি ক্রকফোর্ড জাভাস্ক্রিপ্টে আরও পড়তে পারেন : ভাল অংশগুলি


3
সত্যিই খুব সুন্দর, তবে আপনি আসলে base_doএকটি ফাংশন হিসাবে কল করতে পারবেন না , কারণ আপনি thisসেই doপদ্ধতিতে কোনও বাঁধাই হারাবেন । সুতরাং, বেস পদ্ধতির সেটআপটি কিছুটা জটিল, বিশেষত যদি আপনি thisশিশু অবজেক্টের পরিবর্তে বেস অবজেক্টটি ব্যবহার করে এটি কল করতে চান । আমি অনুরূপ কিছু প্রস্তাব করব base_do.apply(me, arguments)
জিউলিও পিয়ানোস্টেলি

শুধু মনে হচ্ছে, তুমি কেন ব্যবহার করবেন না varজন্য base_do? এটি কি উদ্দেশ্যমূলক এবং যদি তাই হয় তবে কেন? এবং, জিওলিওপিয়ানাস্টেল্লি যেমন বলেছিলেন, এই ব্রেকটি কি এই বিরতির সাথে thisআবদ্ধ হয় base_do()বা সেই কলটি thisতার কলকারীকে উত্তরাধিকারী করবে ?
বিনকি

@ বিঙ্কি আমি উদাহরণটি আপডেট করেছি। সেখানে varথাকা উচিত। call(বা apply) ব্যবহার করা আমাদের thisসঠিকভাবে বাঁধাই করতে দেয় ।
ম্যাগনার

10

আমি জানি এই পোস্টটি 4 বছর আগের, কিন্তু আমার সি # ব্যাকগ্রাউন্ডের কারণে আমি ক্লাসের নাম উল্লেখ না করে বেস ক্লাসে কল করার উপায় খুঁজছিলাম বরং সাবক্লাসের কোনও সম্পত্তি দ্বারা এটি অর্জন করছিলাম। তাই ক্রিস্টফের উত্তরে আমার একমাত্র পরিবর্তন হবে

এটা থেকে:

MyClass.prototype.doStuff.call(this /*, args...*/);

এটি:

this.constructor.prototype.doStuff.call(this /*, args...*/);

6
এটি করবেন না, this.constructorসর্বদা নির্দেশ নাও করতে পারে MyClass
বার্গি

ওয়েল, এটি হওয়া উচিত, যদি না কেউ উত্তরাধিকার স্থাপনের চেষ্টা করে। 'এটি' সর্বদা শীর্ষ স্তরের অবজেক্টকে উল্লেখ করা উচিত এবং এর 'কনস্ট্রাক্টর' বৈশিষ্ট্যটি সর্বদা তার নিজস্ব নির্মাণকারী ফাংশনকে নির্দেশ করা উচিত।
ট্রায়ঙ্কো

5

আপনি যদি এই জাতীয় কোনও ক্রিয়া সংজ্ঞায়িত করেন (ওওপি ব্যবহার করে)

function Person(){};
Person.prototype.say = function(message){
   console.log(message);
}

প্রোটোটাইপ ফাংশনটি কল করার দুটি উপায় রয়েছে: 1) একটি উদাহরণ তৈরি করুন এবং অবজেক্ট ফাংশনটিতে কল করুন:

var person = new Person();
person.say('hello!');

এবং অন্য উপায়টি হ'ল ... 2) প্রোটোটাইপ থেকে সরাসরি ফাংশনটি কল করছে:

Person.prototype.say('hello there!');

5

এই সমাধান ব্যবহার করে Object.getPrototypeOf

TestA যে সুপার হয় getName

TestBএকটি শিশু ওভাররাইড করে getNameকিন্তু এছাড়াও আছে getBothNamesযে কল superসংস্করণ getNameসেইসাথে childসংস্করণ

function TestA() {
  this.count = 1;
}
TestA.prototype.constructor = TestA;
TestA.prototype.getName = function ta_gn() {
  this.count = 2;
  return ' TestA.prototype.getName is called  **';
};

function TestB() {
  this.idx = 30;
  this.count = 10;
}
TestB.prototype = new TestA();
TestB.prototype.constructor = TestB;
TestB.prototype.getName = function tb_gn() {
  return ' TestB.prototype.getName is called ** ';
};

TestB.prototype.getBothNames = function tb_gbn() {
  return Object.getPrototypeOf(TestB.prototype).getName.call(this) + this.getName() + ' this object is : ' + JSON.stringify(this);
};

var tb = new TestB();
console.log(tb.getBothNames());


4
function NewClass() {
    var self = this;
    BaseClass.call(self);          // Set base class

    var baseModify = self.modify;  // Get base function
    self.modify = function () {
        // Override code here
        baseModify();
    };
}

4

একটি বিকল্প:

// shape 
var shape = function(type){
    this.type = type;
}   
shape.prototype.display = function(){
    console.log(this.type);
}
// circle
var circle = new shape('circle');
// override
circle.display = function(a,b){ 
    // call implementation of the super class
    this.__proto__.display.apply(this,arguments);
}

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

2

যদি আমি সঠিকভাবে বুঝতে পারি তবে আপনি চান বেসের কার্যকারিতা সর্বদা সম্পাদন করা উচিত, যখন এর একটি অংশটি বাস্তবায়নের জন্য রেখে দেওয়া উচিত।

আপনি ' টেমপ্লেট পদ্ধতি ' ডিজাইন প্যাটার্ন দ্বারা সহায়তা পেতে পারেন ।

Base = function() {}
Base.prototype.do = function() { 
    // .. prologue code
    this.impldo(); 
    // epilogue code 
}
// note: no impldo implementation for Base!

derived = new Base();
derived.impldo = function() { /* do derived things here safely */ }

1

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

function Base() {
}

Base.prototype.foo = function() {
  console.log('called foo in Base');
}

function Sub() {
}

Sub.prototype = new Base();

Sub.prototype.foo = function() {
  console.log('called foo in Sub');
  Base.prototype.foo.call(this);
}

var base = new Base();
base.foo();

var sub = new Sub();
sub.foo();

এটি মুদ্রণ করবে

called foo in Base
called foo in Sub
called foo in Base

প্রত্যাশিত.


1

ES5 এর সাথে আরেকটি উপায় হ'ল স্পষ্টভাবে ব্যবহার করে প্রোটোটাইপ চেইনটি অতিক্রম করা Object.getPrototypeOf(this)

const speaker = {
  speak: () => console.log('the speaker has spoken')
}

const announcingSpeaker = Object.create(speaker, {
  speak: {
    value: function() {
      console.log('Attention please!')
      Object.getPrototypeOf(this).speak()
    }
  }
})

announcingSpeaker.speak()

0

না, আপনাকে কনস্ট্রাক্টরে ডু ফাংশন এবং প্রোটোটাইপের বিভিন্ন নাম দেওয়া দরকার।


0

এছাড়াও, আপনি যদি কেবলমাত্র একটি বিশেষ উদাহরণটিই নয়, সমস্ত পরিস্থিতিতে ওভাররাইড করতে চান তবে এটির সাহায্য হতে পারে।

function MyClass() {}

MyClass.prototype.myMethod = function() {
  alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
  MyClass.prototype.myMethod_original.call( this );
  alert( "doing override");
};

myObj = new MyClass();
myObj.myMethod();

ফলাফল:

doing original
doing override

-1
function MyClass() {}

MyClass.prototype.myMethod = function() {
  alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
  MyClass.prototype.myMethod_original.call( this );
  alert( "doing override");
};

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