জাভাস্ক্রিপ্টে শিশু শ্রেণি থেকে পিতামাতার পদ্ধতিটি কীভাবে কল করবেন?


156

আমি আমার সমস্যার সমাধান খুঁজতে গিয়ে বেশ কয়েক ঘন্টা ব্যয় করেছি তবে এটি হতাশ বলে মনে হচ্ছে।

মূলত আমার চাইল্ড ক্লাস থেকে পিতামাতার পদ্ধতিতে কল করতে হবে তা জানতে হবে। আমি এখন পর্যন্ত যে সমস্ত স্টাফ চেষ্টা করেছি সেগুলি কাজ না করা বা মূল পদ্ধতিটি অতিরিক্ত লেখার মধ্যেই শেষ।

আমি জাভাস্ক্রিপ্টে ওওপি সেট আপ করতে নিম্নলিখিত কোডটি ব্যবহার করছি:

// SET UP OOP
// surrogate constructor (empty function)
function surrogateCtor() {}

function extend(base, sub) {
    // copy the prototype from the base to setup inheritance
    surrogateCtor.prototype = base.prototype;
    sub.prototype = new surrogateCtor();
    sub.prototype.constructor = sub;
}

// parent class
function ParentObject(name) {
    this.name = name;
}
// parent's methods
ParentObject.prototype = {
    myMethod: function(arg) {
        this.name = arg;
    }
}

// child
function ChildObject(name) {
    // call the parent's constructor
    ParentObject.call(this, name);
    this.myMethod = function(arg) {
        // HOW DO I CALL THE PARENT METHOD HERE?
        // do stuff
    }
}

// setup the prototype chain
extend(ParentObject, ChildObject);

আমাকে প্রথমে পিতামাতার পদ্ধতিতে কল করতে হবে এবং তারপরে এটিতে শিশু শ্রেণিতে আরও কিছু জিনিস যুক্ত করা দরকার।

বেশিরভাগ ওওপি ভাষায় যেগুলি কল করার মতো সহজ হবে parent.myMethod() তবে জাভাস্ক্রিপ্টে এটি কীভাবে হয়েছিল তা আমি সত্যিই বুঝতে পারি না।

কোন সাহায্যের অনেক প্রশংসা করা হয়, আপনাকে ধন্যবাদ!

উত্তর:


196

এটি কিভাবে সম্পন্ন হয়েছে তা এখানে: ParentClass.prototype.myMethod();

বা যদি আপনি বর্তমান দৃষ্টান্তের প্রসঙ্গে এটি কল করতে চান তবে আপনি এটি করতে পারেন: ParentClass.prototype.myMethod.call(this)

একই সাথে আর্গুমেন্ট সহ শিশু শ্রেণি থেকে পিতামাতার পদ্ধতিটি কল করা যায়: ParentClass.prototype.myMethod.call(this, arg1, arg2, ..)* ইঙ্গিত: অ্যারে হিসাবে যুক্তিগুলি পাস করার apply()পরিবর্তে ব্যবহার করুন call()


7
আপনি যদি বর্তমানের উদাহরণের প্রসঙ্গে এটি কল করতে চান তবে আপনাকে নিজের ParentClass.prototype.myMethod.apply() or নির্মাণকারীর মতো করে প্যারেন্টক্লাস.প্রোটোটাইপ.মিমেথোডক্যাল () do করতে হবে।
জেএমএম

3
কেবল এটি যুক্ত করে যদি আপনি যুক্তি দিয়ে কল করতে চান তবে তারা প্রয়োগ বা কল ফাংশনটির ভিতরে যান ( ParentClass.prototype.myMethod.call(this, arg1, arg2, arg3...);)
গেরশম

আমি বুঝতে পারছি না। যদি আমি প্যারেন্টক্লাস.প্রোটোটাইপ.মিমেথোডকেলকে কল করি (এটি); চাইল্ডঅবজেক্টের মাইমথোড থেকে আমার একটি ত্রুটি পেয়েছে "আনকাটড টাইপ এরিয়ার: অপরিজ্ঞাত সম্পত্তি 'কল' পড়তে পারে না।
zhekaus

@ ঝেকাউস, এর অর্থ হ'ল myMethodআপনার ক্লাসে নেই।
ইয়ামসালাত

2
আমি বর্তমানে কোনও আইটেমের পদ্ধতি ঘোষণা করার জন্য this.myFun = ফাংশন () {using ব্যবহার করছি, সুতরাং প্যারেন্টক্লাস.প্রোটোটাইপ.মাইফুন.call কল করুন (...) কাজ করছে না, তাই আমাকে কারেন্টক্লাস.প্রোটোটাইপ.মাইফুন.ক্ল্যাক্ট ব্যবহার করতে হবে ( ...)। জেএস হ'ল ... একটি বাজে কথা, আমাদের আসল ওওপি ব্যবহার করা উচিত।
লোনিক্স

156

ES6 শৈলী আপনাকে superকীওয়ার্ডের মতো নতুন বৈশিষ্ট্যগুলি ব্যবহার করতে দেয় । superআপনি যখন ES6 ক্লাস সিনট্যাক্স ব্যবহার করছেন তখন মূল শব্দটি প্যারেন্ট ক্লাসের প্রসঙ্গে। খুব সাধারণ উদাহরণ হিসাবে, চেকআউট:

class Foo {
    static classMethod() {
        return 'hello';
    }
}

class Bar extends Foo {
    static classMethod() {
        return super.classMethod() + ', too';
    }
}
Bar.classMethod(); // 'hello, too'

এছাড়াও, আপনি superপ্যারেন্ট কন্সট্রাক্টরকে কল করতে ব্যবহার করতে পারেন :

class Foo {}

class Bar extends Foo {
    constructor(num) {
        let tmp = num * 2; // OK
        this.num = num; // ReferenceError
        super();
        this.num = num; // OK
    }
}

এবং অবশ্যই আপনি পিতামাতার শ্রেণীর বৈশিষ্ট্য অ্যাক্সেস করতে এটি ব্যবহার করতে পারেন super.prop। সুতরাং, ES6 ব্যবহার করুন এবং খুশি হন।


10
@ fsinisi90 আমি বিশ্বাস করি, প্রশ্নটি পিতামাতার শ্রেণি পদ্ধতি সম্পর্কে নয়, বরং পিতামাতার উদাহরণ পদ্ধতি সম্পর্কে যা কেবল এসএস-এর মতো সুপার কীওয়ার্ড দিয়ে কল করা যায় না।
এমসিএমএলএক্সএক্সএক্সএক্সআইআইআইই

এটি স্থিতিশীল নয় এমন পদ্ধতিগুলির জন্যও কাজ করে (ক্রোমের সাথে পরীক্ষিত, কোনও ট্রান্সিলাইং ছাড়াই, স্ট্যাটিক কীওয়ার্ড চেষ্টা করে না)
জিয়ানলুকা কাসাটি

কেন এটি superবলা প্রয়োজন ? "পুরানো" জেএস এর মধ্যে কি কোনও সমতা আছে?
1252748

3
সুপার () কে অন্য কোনও কিছুর আগে চাইল্ড ক্লাস কনস্ট্রাক্টরে ডাকতে হবে।
ব্যবহারকারী 938363

1
@ জিয়ানলুকাসিটি: আপনি কেবল super()স্থির পদ্ধতিতে ব্যবহার করতে পারেন ; দেখে মনে হচ্ছে আপনি এটি নির্মাণে ব্যবহার করেছেন।
জেডজুম্বো

5

এটি করার জন্য, আপনি ClassES6 এর বিমূর্ততার সাথে সীমাবদ্ধ নন । __proto__সম্পত্তির মাধ্যমে প্যারেন্ট কন্সট্রাক্টরের প্রোটোটাইপ পদ্ধতিগুলি অ্যাক্সেস করা সম্ভব (আমি যথেষ্ট নিশ্চিত যে সহযোগী জেএস কোডাররা এটি হ্রাস করা হয়েছে বলে অভিযোগ করার জন্য থাকবে) যা অবমূল্যায়ন করা হয়েছে তবে একই সাথে আবিষ্কার করেছেন যে এটি আসলে উপ-শ্রেণিবদ্ধকরণের প্রয়োজনীয়তার জন্য প্রয়োজনীয় সরঞ্জাম ( বিশেষত অ্যারে সাব-ক্লাসিংয়ের প্রয়োজন যদিও)) সুতরাং __proto__আমি জানি যে সমস্ত বড় জেএস ইঞ্জিনে সম্পত্তি এখনও পাওয়া যায়, ES6 এর Object.getPrototypeOf()কার্যকারিতাটি এর উপরে প্রবর্তন করেছিল । super()এই সরঞ্জামটি Classবিমূর্ততা এই একটি সিনট্যাক্স চিনি নেই।

সুতরাং যদি আপনার পিতামাতার নির্মাণকারীর নামের অ্যাক্সেস না থাকে এবং Classআপনি এখনও নীচের মতো করতে পারেন এমন বিমূর্তিটি ব্যবহার করতে চান না ;

function ChildObject(name) {
    // call the parent's constructor
    ParentObject.call(this, name);
    this.myMethod = function(arg) {
    //this.__proto__.__proto__.myMethod.call(this,arg);
    Object.getPrototypeOf(Object.getPrototypeOf(this)).myMethod.call(this,arg);
    }
}

4

একাধিক উত্তরাধিকার স্তরের ক্ষেত্রে, এই ফাংশনটি অন্য ভাষায় একটি সুপার () পদ্ধতি হিসাবে ব্যবহার করা যেতে পারে। এখানে কয়েকটি পরীক্ষার সাহায্যে একটি ডেমো ফলল দেওয়া হচ্ছে , আপনি নিজের পদ্ধতির ব্যবহারের অভ্যন্তরে এটি এটি ব্যবহার করতে পারেন:call_base(this, 'method_name', arguments);

এটি বেশ সাম্প্রতিক ইএস ফাংশনগুলি ব্যবহার করে, পুরানো ব্রাউজারগুলির সাথে সামঞ্জস্যের গ্যারান্টি নেই। আইই 11, এফএফ 29, সিএইচ 35-তে পরীক্ষিত।

/**
 * Call super method of the given object and method.
 * This function create a temporary variable called "_call_base_reference",
 * to inspect whole inheritance linage. It will be deleted at the end of inspection.
 *
 * Usage : Inside your method use call_base(this, 'method_name', arguments);
 *
 * @param {object} object The owner object of the method and inheritance linage
 * @param {string} method The name of the super method to find.
 * @param {array} args The calls arguments, basically use the "arguments" special variable.
 * @returns {*} The data returned from the super method.
 */
function call_base(object, method, args) {
    // We get base object, first time it will be passed object,
    // but in case of multiple inheritance, it will be instance of parent objects.
    var base = object.hasOwnProperty('_call_base_reference') ? object._call_base_reference : object,
    // We get matching method, from current object,
    // this is a reference to define super method.
            object_current_method = base[method],
    // Temp object wo receive method definition.
            descriptor = null,
    // We define super function after founding current position.
            is_super = false,
    // Contain output data.
            output = null;
    while (base !== undefined) {
        // Get method info
        descriptor = Object.getOwnPropertyDescriptor(base, method);
        if (descriptor !== undefined) {
            // We search for current object method to define inherited part of chain.
            if (descriptor.value === object_current_method) {
                // Further loops will be considered as inherited function.
                is_super = true;
            }
            // We already have found current object method.
            else if (is_super === true) {
                // We need to pass original object to apply() as first argument,
                // this allow to keep original instance definition along all method
                // inheritance. But we also need to save reference to "base" who
                // contain parent class, it will be used into this function startup
                // to begin at the right chain position.
                object._call_base_reference = base;
                // Apply super method.
                output = descriptor.value.apply(object, args);
                // Property have been used into super function if another
                // call_base() is launched. Reference is not useful anymore.
                delete object._call_base_reference;
                // Job is done.
                return output;
            }
        }
        // Iterate to the next parent inherited.
        base = Object.getPrototypeOf(base);
    }
}

2

ডগলাস ক্রকফোর্ড ধারণার ভিত্তিতে কিছু সম্পর্কে কীভাবে:

    function Shape(){}

    Shape.prototype.name = 'Shape';

    Shape.prototype.toString = function(){
        return this.constructor.parent
            ? this.constructor.parent.toString() + ',' + this.name
            : this.name;
    };


    function TwoDShape(){}

    var F = function(){};

    F.prototype = Shape.prototype;

    TwoDShape.prototype = new F();

    TwoDShape.prototype.constructor = TwoDShape;

    TwoDShape.parent = Shape.prototype;

    TwoDShape.prototype.name = '2D Shape';


    var my = new TwoDShape();

    console.log(my.toString()); ===> Shape,2D Shape

2

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

সন্তানের উদাহরণ -> সন্তানের প্রোটোটাইপ (শিশু পদ্ধতি সহ) -> পিতামাতার প্রোটোটাইপ (পিতামাতার পদ্ধতি সহ) -> অবজেক্ট প্রোটোটাইপ -> নাল

শিশু পদ্ধতিগুলি ছায়াযুক্ত পিতামাতার পদ্ধতিগুলিও কল করতে পারে, নীচে তিনটি নক্ষত্রমুখে দেখানো হয়েছে।

এখানে কীভাবে:

//Parent constructor
function ParentConstructor(firstName){
    //add parent properties:
    this.parentProperty = firstName;
}

//add 2 Parent methods:
ParentConstructor.prototype.parentMethod = function(argument){
    console.log(
            "Parent says: argument=" + argument +
            ", parentProperty=" + this.parentProperty +
            ", childProperty=" + this.childProperty
    );
};

ParentConstructor.prototype.commonMethod = function(argument){
    console.log("Hello from Parent! argument=" + argument);
};

//Child constructor    
function ChildConstructor(firstName, lastName){
    //first add parent's properties
    ParentConstructor.call(this, firstName);

    //now add child's properties:
    this.childProperty = lastName;
}

//insert Parent's methods into Child's prototype chain
var rCopyParentProto = Object.create(ParentConstructor.prototype);
rCopyParentProto.constructor = ChildConstructor;
ChildConstructor.prototype = rCopyParentProto;

//add 2 Child methods:
ChildConstructor.prototype.childMethod = function(argument){
    console.log(
            "Child says: argument=" + argument +
            ", parentProperty=" + this.parentProperty +
            ", childProperty=" + this.childProperty
    );
};

ChildConstructor.prototype.commonMethod = function(argument){
    console.log("Hello from Child! argument=" + argument);

    // *** call Parent's version of common method
    ParentConstructor.prototype.commonMethod(argument);
};

//create an instance of Child
var child_1 = new ChildConstructor('Albert', 'Einstein');

//call Child method
child_1.childMethod('do child method');

//call Parent method
child_1.parentMethod('do parent method');

//call common method
child_1.commonMethod('do common method');


1

মাল্টিলেভেল প্রোটোটাইপ লুকোচুরির জন্য অনেক সহজ এবং আরও কমপ্যাক্ট সমাধান রয়েছে তবে এর জন্য Proxyসমর্থন প্রয়োজন requires ব্যবহার: SUPER(<instance>).<method>(<args>)উদাহরণস্বরূপ, দুটি ক্লাস অভিমানী জন্য Aএবং B extends Aপদ্ধতি সঙ্গে m: SUPER(new B).m()

function SUPER(instance) {
    return new Proxy(instance, {
        get(target, prop) {
            return Object.getPrototypeOf(Object.getPrototypeOf(target))[prop].bind(target);
        }
    });
}

0

আপনাকে অভিভাবক এর প্রোটোটাইপ দ্বারা পিতা বা মাতা পদ্ধতি কল করতে পারেন সময় আপনি ব্যবহার করার জন্য বর্তমান শিশু উদাহরণস্বরূপ পাস করতে হবে call, applyঅথবা bindপদ্ধতি। bindতাই আমি সুপারিশ নয় যে আপনি এটা ছাড়া কর্মক্ষমতা জন্য যত্ন শুধুমাত্র একবার বলা পদ্ধতি একটি নতুন ফাংশন তৈরি করবে।

বিকল্প হিসাবে আপনি শিশু পদ্ধতিটি প্রতিস্থাপন করতে পারেন এবং আসল শিশু পদ্ধতিটি কল করার সময় পিতামাতার পদ্ধতিটি স্থাপন করতে পারেন।

function proxy(context, parent){
  var proto = parent.prototype;
  var list = Object.getOwnPropertyNames(proto);
  
  var child = {};
  for(var i=0; i<list.length; i++){
    var key = list[i];

    // Create only when child have similar method name
    if(context[key] !== proto[key]){
      child[key] = context[key];
      context[key] = function(){
        context.super = proto[key];
        return child[key].apply(context, arguments);
      }
    }
  }
}

// ========= The usage would be like this ==========

class Parent {
  first = "Home";

  constructor(){
    console.log('Parent created');
  }

  add(arg){
    return this.first + ", Parent "+arg;
  }
}

class Child extends Parent{
  constructor(b){
    super();
    proxy(this, Parent);
    console.log('Child created');
  }

  // Comment this to call method from parent only
  add(arg){
    return this.super(arg) + ", Child "+arg;
  }
}

var family = new Child();
console.log(family.add('B'));

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