जावास्क्रिप्ट में एक वस्तु का विस्तार


164

मैं वर्तमान में जावा से जावास्क्रिप्ट में बदल रहा हूं, और मेरे लिए यह पता लगाना थोड़ा कठिन है कि वस्तुओं को कैसे बढ़ाया जाए, जो मैं करना चाहता हूं।

मैंने इंटरनेट पर कई लोगों को ऑब्जेक्ट पर विस्तार नामक एक विधि का उपयोग करते देखा है। कोड इस तरह दिखेगा:

var Person = {
   name : 'Blank',
   age  : 22
}

var Robot = Person.extend({
   name : 'Robo',
   age  : 4
)}

var robot = new Robot();
alert(robot.name); //Should return 'Robo'

क्या किसी को पता है कि यह काम कैसे करना है? मैंने सुना है कि आपको लिखने की ज़रूरत है

Object.prototype.extend = function(...);

लेकिन मुझे नहीं पता कि इस प्रणाली को कैसे काम करना है। यदि यह संभव नहीं है, तो कृपया मुझे एक और विकल्प दिखाएं जो एक वस्तु का विस्तार करता है।


सच लौटना; लेकिन यही कारण है कि मैं पूछ रहा हूं :)
विटज़

2
मैं एमडीएन पर इस सुंदर ट्यूपरर्स के माध्यम से जाने का सुझाव दूंगा: - developer.mozilla.org/en/…
प्रणव

यदि आप उन अच्छे डॉक्स को पढ़ने के बाद, जो आप अभी भी एक extendसमारोह के बारे में उत्सुक हैं , तो मैंने यहां एक उदाहरण स्थापित किया है: jsfiddle.net/k9LRd
Codrin Eugeniu

2
मैं इसके बारे में सख्ती से नहीं सोचने का सुझाव भी दूंगा कि 'जावा से जावास्क्रिप्ट में बदलना' और अधिक से अधिक 'एक नई भाषा सीखना, जावास्क्रिप्ट, जो कि जावा के समान सिंटैक्स है'
टौनी लेघ

जवाबों:


195

आप व्यक्ति के प्रोटोटाइप ऑब्जेक्ट से 'इनहेरिट' करना चाहते हैं:

var Person = function (name) {
    this.name = name;
    this.type = 'human';
};

Person.prototype.info = function () {
    console.log("Name:", this.name, "Type:", this.type);
};

var Robot = function (name) {
    Person.apply(this, arguments);
    this.type = 'robot';
};

Robot.prototype = Person.prototype;  // Set prototype to Person's
Robot.prototype.constructor = Robot; // Set constructor back to Robot

person = new Person("Bob");
robot = new Robot("Boutros");

person.info();
// Name: Bob Type: human

robot.info();
// Name: Boutros Type: robot

4
मेरा एक सवाल है: Person()जब आप करते हैं तो निर्माणकर्ता को कैसे बुलाया जाता है new Robot()? मुझे ऐसा लगता है कि आप के बजाय करने का है कि आधार वर्ग निर्माता बुलाना चाहिए this.name = name;में Robot()निर्माता ...
एलेक्सिस विके

21
@AlexisWilke: हां, आपको फोन करना चाहिए Person.apply(this, arguments);। इसके Robot.prototype = Object.create(Person.prototype);बजाय इसका इस्तेमाल करना बेहतर होगा new Person();
फेलिक्स क्लिंग

18
जैसा कि फेलिक्स ने कहा है, 'Robot.prototype = Person.prototype;' एक बुरा विचार है अगर कोई भी 'रोबोट' प्रकार का अपना स्वयं का प्रोटोटाइप उदाहरण चाहता है। नए रोबोट विशिष्ट कार्यों को जोड़ना भी व्यक्ति को जोड़ देगा।
जेम्स विल्किंस

20
यह उदाहरण पूरी तरह से गलत है। ऐसा करके आप व्यक्ति के प्रोटोटाइप को बदल देते हैं। यह वंशानुक्रम नहीं है और आप व्यक्ति वर्ग में एक बड़ी गड़बड़ी का जोखिम उठाते हैं। वह उत्तर देखें जो Object.create () का उपयोग करने की अनुशंसा करता है। यह चीजों को करने का सही तरीका है।
निकोलस-वैन

6
@osahyoun इस उत्तर में Google की खोज में उच्च रैंकिंग है। मैं वास्तव में आपको सुझाव दूंगा कि आप कोड को ठीक करें और प्रोटोटाइप श्रृंखला को ठीक करें जैसा कि अन्य टिप्पणियों द्वारा यहां सुझाया गया है।
राफेलियर

103

"नया" कीवर्ड के बिना दुनिया।

और Object.create () के साथ सरल "गद्य-जैसा" वाक्य रचना।

* यह उदाहरण ES6 वर्गों के लिए अद्यतन किया गया है।

सबसे पहले, याद रखें कि जावास्क्रिप्ट एक प्रोटोटाइप भाषा है । यह वर्ग-आधारित नहीं है। इसलिए, प्रोटोटाइप के रूप में लिखना इसकी वास्तविक प्रकृति को उजागर करता है, और बहुत ही सरल, गद्य जैसा और शक्तिशाली हो सकता है।

TLDR;

const Person = { name: 'Anonymous' } // person has a name

const jack = Object.create(Person)   // jack is a person
jack.name = 'Jack'                   // and has a name 'Jack'

नहीं, आपको निर्माणकर्ताओं की आवश्यकता नहीं है, कोई newतात्कालिकता नहीं है ( पढ़ें कि आपको इसका उपयोग क्यों नहीं करना चाहिएnew ), नहीं super, कोई मज़ेदार मजाक नहीं है __construct। आप बस ऑब्जेक्ट बनाते हैं और फिर उन्हें विस्तारित या मॉर्फ करते हैं।

( यदि आप गेटर्स और सेटर के बारे में जानते हैं, तो "आगे की रीडिंग" सेक्शन देखें कि यह पैटर्न आपको फ्री गेटर्स कैसे देता है और एक तरह से बसता है कि जावास्क्रिप्ट मूल रूप से किसके लिए है, और वे कितने शक्तिशाली हैं ।)

गद्य-जैसा सिंटैक्स: बेस प्रोटोपे

const Person = {

   //attributes
   firstName : 'Anonymous', 
   lastName: 'Anonymous',
   birthYear  : 0,
   type : 'human',

   //methods
   name() { return this.firstName + ' ' + this.lastName },
   greet() {
       console.log('Hi, my name is ' + this.name() + ' and I am a ' + this.type + '.' )
   },
   age() {
      // age is a function of birth time.
   }
}

const person = Object.create(Person). // that's it!

एक नज़र में, बहुत पठनीय लगता है।

विस्तार, का वंशज बनाना Person

* सही शब्द हैं prototypes , और उनके descendantsclassesकोई जरूरत नहीं है , और कोई जरूरत नहीं है instances

const Skywalker = Object.create(Person)
Skywalker.lastName = 'Skywalker'

const anakin = Object.create(Skywalker)
anakin.firstName = 'Anakin'
anakin.birthYear = '442 BBY'
anakin.gender = 'male' // you can attach new properties.
anakin.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'

Person.isPrototypeOf(Skywalker) // outputs true
Person.isPrototypeOf(anakin) // outputs true
Skywalker.isPrototypeOf(anakin) // outputs true

बनाने का एक तरीका "डिफ़ॉल्ट" तरीका प्रदान करता है descendant , एक #createविधि संलग्न करके :

Skywalker.create = function(firstName, gender, birthYear) {

    let skywalker = Object.create(Skywalker)

    Object.assign(skywalker, {
        firstName,
        birthYear,
        gender,
        lastName: 'Skywalker',
        type: 'human'
    })

    return skywalker
}

const anakin = Skywalker.create('Anakin', 'male', '442 BBY')

नीचे दिए गए तरीके कम पठनीयता हैं:

"शास्त्रीय" समकक्ष की तुलना करें:

function Person (firstName, lastName, birthYear, type) {
    this.firstName = firstName 
    this.lastName = lastName
    this.birthYear = birthYear
    this.type = type
}

// attaching methods
Person.prototype.name = function() { return firstName + ' ' + lastName }
Person.prototype.greet = function() { ... }
Person.prototype.age = function() { ... }

function Skywalker(firstName, birthYear) {
    Person.apply(this, [firstName, 'Skywalker', birthYear, 'human'])
}

// confusing re-pointing...
Skywalker.prototype = Person.prototype
Skywalker.prototype.constructor = Skywalker

const anakin = new Skywalker('Anakin', '442 BBY')

Person.isPrototypeOf(anakin) // returns false!
Skywalker.isPrototypeOf(anakin) // returns false!

"शास्त्रीय" शैली का उपयोग करके कोड पठनीयता इतनी अच्छी नहीं है।

ईएस 6 क्लासेस

बेशक, इन समस्याओं में से कुछ ES6 वर्गों द्वारा मिटा दी जाती हैं, लेकिन फिर भी:

class Person {
    constructor(firstName, lastName, birthYear, type) {
        this.firstName = firstName 
        this.lastName = lastName
        this.birthYear = birthYear
        this.type = type
    }
    name() { return this.firstName + ' ' + this.lastName }
    greet() { console.log('Hi, my name is ' + this.name() + ' and I am a ' + this.type + '.' ) }
}

class Skywalker extends Person {
    constructor(firstName, birthYear) {
        super(firstName, 'Skywalker', birthYear, 'human')
    }
}

const anakin = new Skywalker('Anakin', '442 BBY')

// prototype chain inheritance checking is partially fixed.
Person.isPrototypeOf(anakin) // returns false!
Skywalker.isPrototypeOf(anakin) // returns true

आधार प्रोटोटाइप शाखा

// create a `Robot` prototype by extending the `Person` prototype:
const Robot = Object.create(Person)
Robot.type = 'robot'
Robot.variant = '' // add properties for Robot prototype

करने के लिए अद्वितीय तरीके संलग्न करें Robot

// Robots speak in binaries, so we need a different greet function:
Robot.machineGreet = function() { /*some function to convert strings to binary */ }

// morphing the `Robot` object doesn't affect `Person` prototypes
anakin.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'
anakin.machineGreet() // error

वंशानुक्रम की जाँच करना

Person.isPrototypeOf(Robot) // outputs true
Robot.isPrototypeOf(Skywalker) // outputs false

आपको वह सब कुछ मिल गया है जो आपको पहले से ही चाहिए! न कंस्ट्रक्टर, न इंस्टेंटेशन। साफ, स्पष्ट गद्य।

आगे की पढाई

योग्यता, विन्यास और मुक्त गेटर्स और सेटर्स!

मुफ्त पाने वालों और बसने वालों या अतिरिक्त विन्यास के लिए, आप Object.create () के दूसरे तर्क उर्फ ​​गुण का उपयोग कर सकते हैं। यह # Object.defineProperty , और # Object.defineProperties में भी उपलब्ध है

यह समझने के लिए कि यह कितना शक्तिशाली है, मान लीजिए कि हम चाहते हैं कि सभी Robotधातु से बने हों (के माध्यम से writable: false), और powerConsumptionमूल्यों को मानकीकृत करें (गेटर्स और सेटर्स के माध्यम से)।

const Robot = Object.create(Person, {
    // define your property attributes
    madeOf: { 
        value: "metal",
        writable: false,
        configurable: false,
        enumerable: true
    },
    // getters and setters, how javascript had (naturally) intended.
    powerConsumption: {
        get() { return this._powerConsumption },
        set(value) { 
            if (value.indexOf('MWh')) return this._powerConsumption = value.replace('M', ',000k') 
            this._powerConsumption = value
            throw new Error('Power consumption format not recognised.')
        }  
    }
})

const newRobot = Object.create(Robot)
newRobot.powerConsumption = '5MWh'
console.log(newRobot.powerConsumption) // outputs 5,000kWh

और सभी प्रोटोटाइप कुछ और Robotनहीं हो सकते madeOfक्योंकि writable: false

const polymerRobot = Object.create(Robot)

polymerRobot.madeOf = 'polymer'

console.log(polymerRobot.madeOf) // outputs 'metal'

मिक्सिंस (# Object.assign का उपयोग करके) - अनाकिन स्काईवॉकर

क्या आप समझ सकते हैं कि यह कहां चल रहा है ...?

const darthVader = Object.create(anakin)
// for brevity, property assignments are skipped because you get the point by now.

Object.assign(darthVader, Robot)

डार्थ वादर के तरीके निम्नलिखित हैं Robot:

darthVader.greet() // inherited from `Person`, outputs "Hi, my name is Darth Vader..."
darthVader.machineGreet() // inherited from `Robot`, outputs 001010011010...

अन्य विषम चीजों के साथ:

console.log(darthVader.type) // outputs robot.
Robot.isPrototypeOf(darthVader) // returns false.
Person.isPrototypeOf(darthVader) // returns true.

खैर, चाहे डार्थ वाडर आदमी हो या मशीन वास्तव में व्यक्तिपरक है:

"वह अब आदमी से ज्यादा मशीन है, मुड़ और बुराई।" - ओबी-वान केनबी

"मुझे पता है कि तुममें अच्छाई है।" - ल्यूक स्क्यवाल्कर

अतिरिक्त - # Object.assign के साथ थोड़ा कम सिंटैक्स

सभी संभावना में, यह पैटर्न आपके सिंटैक्स को छोटा करता है। लेकिन ES6 # Object.assign कुछ और छोटा कर सकता है (पुराने ब्राउज़र पर उपयोग करने के लिए पॉलीफ़िल, ES6 पर MDN देखें )।

//instead of this
const Robot = Object.create(Person)
Robot.name = "Robot"
Robot.madeOf = "metal"

//you can do this
const Robot = Object.create(Person)
Object.assign(Robot, {
    name: "Robot",
    madeOf: "metal"
    // for brevity, you can imagine a long list will save more code.
})

8
एक निर्माण कार्य का उपयोग नहीं करने के लिए एक उत्थान है।
nsmarks

1
"शास्त्रीय-प्रशिक्षित" प्रोग्रामर, इससे आपका क्या मतलब है?
पेट्रा

1
मैं एक शास्त्रीय ओओपी मानसिकता से आता हूं और इस जवाब से मुझे बहुत मदद मिली। कोड पर दो प्रश्न: 1) क्या आज ES2015 Object.assign(Robot, {a:1}आपके extend()तरीके के लिए एक अच्छा विकल्प है ? 2) कैसे greet()विधि को ओवरराइड करने के लिए तो यह एक ही पाठ लौटाता है, लेकिन "अभिवादन ओवरराइड" के साथ जोड़ा जाता है?
बैरी स्टेस

2
1) #Object.assignएक अच्छे विकल्प की तरह दिखता है। लेकिन ब्राउज़र का समर्थन कम है। 2) आप __proto__अपने प्रोटोटाइप के ग्रीटिंग फ़ंक्शन तक पहुंचने के लिए ऑब्जेक्ट की संपत्ति का उपयोग करेंगे । तब आप प्रोटोटाइप अभिवादन फ़ंक्शन को कॉलली के दायरे के साथ पारित करते हैं। इस मामले में फ़ंक्शन एक कंसोल लॉग था, इसलिए यह "एपेंड" करना संभव नहीं है। लेकिन इस उदाहरण से मुझे लगता है कि आपको बहाव मिलेगा। skywalker.greet = function() { this.__proto__.greet.call(this); console.log('a greet override'); }
कैल्विन्ट्रॉकर

1
खैर यह एक चर्चा है कि ECMAScript भाषा विनिर्देशन रखरखाव के साथ होना चाहिए। मैं आम तौर पर सहमत हूं, लेकिन मेरे पास जो है उसके साथ काम करना होगा।

51

यदि आपने अभी तक एक तरीका नहीं निकाला है, तो Object.prototypeनीचे दिखाए गए अनुसार विस्तार फ़ंक्शन जोड़ने के लिए जावास्क्रिप्ट ऑब्जेक्ट्स की साहचर्य संपत्ति का उपयोग करें।

Object.prototype.extend = function(obj) {
   for (var i in obj) {
      if (obj.hasOwnProperty(i)) {
         this[i] = obj[i];
      }
   }
};

फिर आप नीचे दिखाए गए अनुसार इस फ़ंक्शन का उपयोग कर सकते हैं।

var o = { member: "some member" };
var x = { extension: "some extension" };

o.extend(x);

18
खबरदार कि यह 'मूल' कक्षा में वस्तुओं / सरणियों का उपयोग करते समय 'बच्चे' वर्ग में मूल वस्तु के लिए संकेत पैदा करेगा। विस्तृत करने के लिए: यदि आपके पास अपने मूल वर्ग में कोई ऑब्जेक्ट या सरणी है, तो इसे उस आधार पर फैली हुई चाइल्ड क्लास में संशोधित करके, वास्तव में इसे सभी बच्चों की कक्षाओं के लिए संशोधित किया जाएगा जो इस बेस क्लास पर विस्तार करते हैं।
हेरोल्ड

हेरोल्ड, इस तथ्य को उजागर करने के लिए धन्यवाद। यह महत्वपूर्ण है कि जो कोई भी वस्तु / सरणियों के लिए जाँच करता है और उनकी प्रतियां बनाता है, उसे शामिल करने के लिए फ़ंक्शन का उपयोग करता है।
टोमिलाय

30

अलग दृष्टिकोण: Object.create

@Osahyoun उत्तर के अनुसार, मैं निम्नलिखित को व्यक्ति के प्रोटोटाइप ऑब्जेक्ट से 'विरासत' के लिए एक बेहतर और कुशल तरीका मानता हूं:

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

Person.prototype.info = function(){
    console.log("Name:", this.name, "Type:", this.type);
}

function Robot(name){
    Person.call(this, name)
    this.type = 'robot';
}

// Set Robot's prototype to Person's prototype by
// creating a new object that inherits from Person.prototype,
// and assigning it to Robot.prototype
Robot.prototype = Object.create(Person.prototype);

// Set constructor back to Robot
Robot.prototype.constructor = Robot;

नए उदाहरण बनाएँ:

var person = new Person("Bob");
var robot = new Robot("Boutros");

person.info(); // Name: Bob Type: human
robot.info();  // Name: Boutros Type: robot

अब, Object.create का उपयोग करके :

Person.prototype.constructor !== Robot

MDN प्रलेखन की भी जाँच करें ।


2
बस कहना चाहते हैं @GaretClaborn यह सही ढंग से काम करता है, लेकिन आप nameमूल निर्माता को पैरामीटर नहीं दे रहे हैं , जैसे: jsfiddle.net/3brm0a7a/3 (अंतर # 8 पंक्ति में है)
xPheee

1
@xPheRe आह मैं देखता हूं, धन्यवाद। मैंने उस परिवर्तन को प्रतिबिंबित करने के लिए उत्तर को संपादित किया
Garet Claborn

1
@xPheRe, मुझे लगता है कि जब मैंने इस समाधान को जोड़ा तो मैं एक बिंदु साबित करने पर अधिक ध्यान केंद्रित कर रहा था। धन्यवाद।
लोर एलरोम

1
अच्छा उत्तर +1, आप ECMAScript 6 पर एक नज़र डाल सकते हैं। कीवर्ड क्लास और
एक्सटेंड

26

ES6 में , आप जैसे फैल ऑपरेटर का उपयोग कर सकते हैं

var mergedObj = { ...Obj1, ...Obj2 };

ध्यान दें कि Object.assign () ट्रिगर सेटर करता है जबकि प्रसार सिंटैक्स नहीं करता है।

अधिक जानकारी के लिए लिंक, एमडीएन-स्प्रेड सिंटैक्स देखें


पुराना उत्तर:

ईएस 6 में , Object.assignसंपत्ति मूल्यों की नकल करने के लिए है। {}यदि आप लक्ष्य ऑब्जेक्ट को संशोधित नहीं करना चाहते हैं, तो पहले पैराम के रूप में उपयोग करें (पहला पैराम पारित)।

var mergedObj = Object.assign({}, Obj1, Obj2);

अधिक जानकारी के लिए लिंक देखें, MDN - Object.assign ()

यदि आपको ईएस 5 के लिए पॉलीफ़िल की आवश्यकता है , तो लिंक इसे भी प्रदान करता है। :)


18

और एक और साल बाद, मैं आपको बता सकता हूं कि एक और अच्छा जवाब है।

यदि आप ऑब्जेक्ट / कक्षाओं पर विस्तार करने के लिए प्रोटोटाइप को काम करने के तरीके को पसंद नहीं करते हैं, तो इस पर ध्यान दें: https://github.com/haroldiedema/joii

त्वरित उदाहरण संभावनाओं का कोड (और कई और अधिक):

var Person = Class({

    username: 'John',
    role: 'Employee',

    __construct: function(name, role) {
        this.username = name;
        this.role = role;
    },

    getNameAndRole: function() {
        return this.username + ' - ' + this.role;
    }

});

var Manager = Class({ extends: Person }, {

  __construct: function(name)
  {
      this.super('__construct', name, 'Manager');
  }

});

var m = new Manager('John');
console.log(m.getNameAndRole()); // Prints: "John - Manager"

खैर, मेरे पास अभी भी 2 महीने हैं जब तक 2 साल का समय नहीं है: पी या तो, JOII 3.0 रिलीज होने वाली है :)
हेरोल्ड

1
उस 3 साल बाद बनाओ।

दिलचस्प अवधारणा, लेकिन वाक्यविन्यास वास्तविक बदसूरत दिखता है। ES6 कक्षाएं स्थिर बनने के लिए आप इंतजार कर बेहतर होगा
sleepycal

मैं पूरी तरह @sleepycal से सहमत हूं। लेकिन दुर्भाग्य से, यह सभी प्रमुख / आम ब्राउज़रों द्वारा इसे लागू करने से कम से कम 5 साल पहले होगा। इसलिए उस समय तक, यह करना होगा ...
हेरोल्ड

12

जो लोग अभी भी सरल और सर्वोत्तम दृष्टिकोण के लिए संघर्ष कर रहे हैं, आप Spread Syntaxऑब्जेक्ट को विस्तारित करने के लिए उपयोग कर सकते हैं ।

var person1 = {
      name: "Blank",
      age: 22
    };

var person2 = {
      name: "Robo",
      age: 4,
      height: '6 feet'
    };
// spread syntax
let newObj = { ...person1, ...person2 };
console.log(newObj.height);

नोट: याद रखें कि, संपत्ति का अधिकार सबसे दूर है प्राथमिकता होगी। इस उदाहरण में, person2दाईं ओर है, इसलिए इसमें रोबोnewObj नाम होगा ।


8

आप अंडरस्कोर लाइब्रेरी जैसे कि अंडरस्कोर .js का उपयोग करने पर विचार करना चाह सकते हैं , जिसका अपना कार्यान्वयन हैextend()

और यह सोर्स कोड देखकर सीखने का एक अच्छा तरीका है। एनोटेट स्रोत कोड पेज काफी उपयोगी है।


1
यह कैसे रेखांकित _.extend()करता है कि अंडरस्कोर। जेएस के
Lemmings19

6

ECMAScript 6.0 से फैली मोज़िला 'घोषणा'

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends

नोट: यह एक प्रायोगिक तकनीक है, जो ECMAScript 6 (हार्मनी) के प्रस्ताव का हिस्सा है।

class Square extends Polygon {
  constructor(length) {
    // Here, it calls the parent class' constructor with lengths
    // provided for the Polygon's width and height
    super(length, length);
    // Note: In derived classes, super() must be called before you
    // can use 'this'. Leaving this out will cause a reference error.
    this.name = 'Square';
  }

  get area() {
    return this.height * this.width;
  }

  set area(value) {
    this.area = value;     } 
}

यह तकनीक गेको (गूगल क्रोम / फायरफॉक्स) - ०३/२०१५ रात्रि में उपलब्ध है।


4

परियोजना के बहुमत में वस्तु के कुछ कार्यान्वयन हैं: अंडरस्कोर, जेकरी, लॉश: विस्तार

शुद्ध जावास्क्रिप्ट कार्यान्वयन भी है, जो ECMAscript 6 का एक हिस्सा है: Object.assign : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_bjects/Object/assign


क्या "शुद्ध जावास्क्रिप्ट कार्यान्वयन" किसी ऐसी चीज़ का संदर्भ नहीं है जिसे सिर्फ जावास्क्रिप्ट के साथ लागू किया जाता है, पर्यावरण-प्रदत्त फ़ंक्शन के लिए नहीं जो मूल रूप से हो सकता है?
3

1
@binki, मेरा मतलब था देशी जावास्क्रिप्ट कार्यान्वयन - ECMAScript 2015 (ES6) मानक का हिस्सा
Cezary Daniel Daniel Nowak

2
Function.prototype.extends=function(ParentClass) {
    this.prototype = new ParentClass();
    this.prototype.constructor = this;
}

फिर:

function Person() {
    this.name = "anonym"
    this.skills = ["abc"];
}
Person.prototype.profile = function() {
    return this.skills.length // 1
};

function Student() {} //well extends fom Person Class
Student.extends(Person)

var s1 = new Student();
s1.skills.push("")
s1.profile() // 2

अद्यतन 01/2017:

कृपया, 2015 के मेरे उत्तर को extendsनजरअंदाज कर दें क्योंकि जावास्क्रिप्ट अब ES6 (Ecmasctipt6) के बाद से कीवर्ड का समर्थन करता है

- ES6:

class Person {
   constructor() {
     this.name = "anonym"
     this.skills = ["abc"];
   }

   profile() {
    return this.skills.length // 1
   }

}

Person.MAX_SKILLS = 10;
class Student extends Person {


} //well extends from Person Class

//-----------------
var s1 = new Student();
s1.skills.push("")
s1.profile() // 2

- ES7:

class Person {
    static MAX_SKILLS = 10;
    name = "anonym"
    skills = ["abc"];

    profile() {
      return this.skills.length // 1
    }

}
class Student extends Person {


} //well extends from Person Class

//-----------------
var s1 = new Student();
s1.skills.push("")
s1.profile() // 2

1
new ParentClass()कंस्ट्रक्टर को अधिलेखित करने से पहले कॉल करके , आपने पहले ही पेरेंट कंस्ट्रक्टर को निष्पादित कर दिया है। मुझे नहीं लगता कि यदि आप मुझसे पूछें तो यह सही व्यवहार है ...
हेरोल्ड

1

सारांश:

जावास्क्रिप्ट एक तंत्र का उपयोग करता है जिसे प्रोटोटाइप इनहेरिटेंस कहा जाता है । एक वस्तु पर एक संपत्ति को देखते समय प्रोटोटाइप विरासत का उपयोग किया जाता है। जब हम जावास्क्रिप्ट में गुणों का विस्तार कर रहे हैं तो हम एक वास्तविक वस्तु से इन गुणों को प्राप्त कर रहे हैं। यह निम्नलिखित तरीके से काम करता है:

  1. जब किसी ऑब्जेक्ट प्रॉपर्टी का अनुरोध किया जाता है, (जैसे myObj.fooया myObj['foo']) जेएस इंजन पहली बार ऑब्जेक्ट पर ही उस प्रॉपर्टी की तलाश करेगा
  2. जब यह गुण ऑब्जेक्ट पर नहीं पाया जाता है तो यह प्रोटोटाइप ऑब्जेक्ट पर प्रोटोटाइप चेन लुक पर चढ़ जाएगा । अगर यह प्रॉपर्टी भी यहां नहीं मिली है तो प्रॉपर्टी मिलने तक यह प्रोटोटाइप चेन पर चढ़ता रहेगा। यदि संपत्ति नहीं मिली है तो यह एक संदर्भ त्रुटि फेंक देगा।

जब हम जावास्क्रिप्ट में किसी ऑब्जेक्ट से विस्तार करना चाहते हैं तो हम इस ऑब्जेक्ट को प्रोटोटाइप चेन में लिंक कर सकते हैं। इसे प्राप्त करने के कई तरीके हैं, मैं आमतौर पर उपयोग किए जाने वाले 2 तरीकों का वर्णन करूंगा।

उदाहरण:

1। Object.create()

Object.create()एक ऐसा कार्य है जो एक वस्तु को एक तर्क के रूप में लेता है और एक नई वस्तु बनाता है। जिस वस्तु को एक तर्क के रूप में पारित किया गया था, वह नव निर्मित वस्तु का प्रोटोटाइप होगा। उदाहरण के लिए:

// prototype of the dog
const dogPrototype = {
  woof: function () { console.log('woof'); }
}

// create 2 dog objects, pass prototype as an argument
const fluffy = Object.create(dogPrototype);
const notFluffy = Object.create(dogPrototype);

// both newly created object inherit the woof 
// function from the dogPrototype
fluffy.woof();
notFluffy.woof();

2. स्पष्ट रूप से प्रोटोटाइप संपत्ति सेट करना

कंस्ट्रक्टर फ़ंक्शन का उपयोग करके ऑब्जेक्ट बनाते समय, हम इसकी प्रोटोटाइप ऑब्जेक्ट प्रॉपर्टी में गुण जोड़ सकते हैं। जिन वस्तुओं का निर्माण किया जाता है वे newकीवर्ड का उपयोग करते समय एक रचनाकार फ़ंक्शन बनाते हैं , उनके प्रोटोटाइप का निर्माण निर्माता फ़ंक्शन के प्रोटोटाइप पर सेट होता है। उदाहरण के लिए:

// Constructor function object
function Dog (name) {
   name = this.name;
}

// Functions are just objects
// All functions have a prototype property
// When a function is used as a constructor (with the new keyword)
// The newly created object will have the consturctor function's
// prototype as its prototype property
Dog.prototype.woof = function () {
  console.log('woof');
}

// create a new dog instance
const fluffy = new Dog('fluffyGoodBoyyyyy');
// fluffy inherits the woof method
fluffy.woof();

// can check the prototype in the following manner
console.log(Object.getPrototypeOf(fluffy));


0

आप बस इसका उपयोग करके कर सकते हैं:

Object.prototype.extend = function(object) {
  // loop through object 
  for (var i in object) {
    // check if the extended object has that property
    if (object.hasOwnProperty(i)) {
      // mow check if the child is also and object so we go through it recursively
      if (typeof this[i] == "object" && this.hasOwnProperty(i) && this[i] != null) {
        this[i].extend(object[i]);
      } else {
        this[i] = object[i];
      }
    }
  }
  return this;
};

अद्यतन: मैं के लिए जाँच this[i] != nullके बाद से nullएक वस्तु है

फिर इसका उपयोग करें जैसे:

var options = {
      foo: 'bar',
      baz: 'dar'
    }

    var defaults = {
      foo: false,
      baz: 'car',
      nat: 0
    }

defaults.extend(options);

यह अच्छी तरह से परिणाम:

// defaults will now be
{
  foo: 'bar',
  baz: 'dar',
  nat: 0
}

0

डाउनलोड करने के लिए कृपया नीचे पढ़ें

  • विस्तार करने के लिए किसी बाहरी पुस्तकालय का उपयोग करने की आवश्यकता नहीं है

  • जावास्क्रिप्ट में, सब कुछ एक वस्तु है (तीन आदिम डेटाटाइप्स को छोड़कर, और यहां तक ​​कि वे स्वचालित रूप से आवश्यक होने पर वस्तुओं के साथ लिपटे होते हैं)। इसके अलावा, सभी ऑब्जेक्ट परस्पर भिन्न हैं।

जावास्क्रिप्ट में क्लास पर्सन

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype = {
    getName: function() {
        return this.name;
    },
    getAge: function() {
        return this.age;
    }
}

/* Instantiate the class. */
var alice = new Person('Alice', 93);
var bill = new Person('Bill', 30);

एक विशिष्ट उदाहरण / वस्तु को संशोधित करें

alice.displayGreeting = function() 
{
    alert(this.getGreeting());
}

कक्षा को संशोधित करें

Person.prototype.getGreeting = function() 
{
    return 'Hi ' + this.getName() + '!';
};

या यूँ कहें: JSON और OBJECT दोनों का विस्तार करें

var k = {
    name : 'jack',
    age : 30
}

k.gender = 'male'; /*object or json k got extended with new property gender*/

रॉस हार, डस्टिन डियाज़ के लिए धन्यवाद


-1

यह आपके गुणों को विस्तारित करेगा ताकि ऑब्जेक्ट पैरामीटर प्रोटोटाइप के साथ एक नई वस्तु का निर्माण किया जा सके बिना पारित वस्तु को बदलकर।

function extend(object) {
    if (object === null)
        throw TypeError;
    if (typeof object !== "object" && typeof object !== "function")
        throw TypeError;
    if (Object.create)
        return Object.create(object);
    function f() {}
    ;
    f.prototype = p;
    return new f();
}

लेकिन अगर आप अपने ऑब्जेक्ट को बिना मापदंडों को संशोधित किए विस्तारित करना चाहते हैं, तो आप अपने ऑब्जेक्ट में एक्सप्रोप्रर्टी जोड़ सकते हैं।

var Person{
//some code
extend: extendProperty
}

//Enforce type checking an Error report as you wish
    function extendProperty(object) {
        if ((object !== null && (typeof object === "object" || typeof object === "function"))){
            for (var prop in object) {
                if (object.hasOwnProperty(prop))
                    this[prop] = object[prop];
            }
        }else{
            throw TypeError; //Not an object
        }
    }

-2

प्रोटोटाइप एक अच्छा तरीका है, लेकिन कभी-कभी प्रोटोटाइप काफी खतरनाक होता है और इससे कीड़े पैदा हो सकते हैं। मैं इसे एक बेस ऑब्जेक्ट में एनकोड करना पसंद करता हूं, जैसे Ember.js इसे Ember.Object.extend और Ember.Object.reopen करता है। यह उपयोग करने के लिए बहुत अधिक सुरक्षित है।

मैं कैसे आप Ember.Object का उपयोग करता है के समान कुछ सेटअप होगा के साथ एक जिस्ट बनाया।

यहाँ लिंक है: https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd


9
Prototyping is a nice way, but prototype is quite dangerous sometimes and can lead to bugs.उससे तुम्हारा क्या मतलब है? जावास्क्रिप्ट में प्रोटोटाइप श्रृंखला का उपयोग करने से कीड़े हो सकते हैं? यह कहना पसंद है कि जावा पर कक्षाओं का उपयोग करने से कीड़े हो सकते हैं और बिल्कुल कोई मतलब नहीं है।
HMR

@ एचएमआर वह कह रहा है कि पर्यावरण-प्रदत्त वस्तु प्रोटोटाइप के परिणामस्वरूप नाजुक कोड होता है, जो भविष्य की मुख्य जावास्क्रिप्ट भाषा सुविधा के साथ संघर्ष कर सकता है। यदि आप Objectप्रोटोटाइप के विस्तार से सब कुछ के लिए एक उपयोगी उपयोगिता फ़ंक्शन जोड़ते हैं , तो आपके फ़ंक्शन का भविष्य जावास्क्रिप्ट फ़ंक्शन के समान नाम हो सकता है और भविष्य में चलने पर आपके कोड को विस्फोट करने का कारण बन सकता है। उदाहरण के लिए, मान लें कि आपने एक repeat()फ़ंक्शन जोड़ा Objectऔर इसे Stringइंस्टेंस पर कॉल किया और फिर आपका जावास्क्रिप्ट रनटाइम ES6 में अपडेट किया गया?
बिंकी

@binki आपके इनपुट के लिए धन्यवाद। आप उन कक्षाओं के प्रोटोटाइप को बदलने के बारे में बात कर रहे हैं जिन्हें आप "स्वयं" नहीं करते हैं और इस प्रकार असंगत संदर्भ को तोड़ रहे हैं: developer.mozilla.org/en/docs/Web/JavaScript/… JS के पास निजी चर नहीं हैं इसलिए आपका API कार्यान्वयन सदस्यों को उजागर करता है , यह आमतौर पर सम्मेलन (अंडरस्कोर के साथ सदस्य नाम शुरू) द्वारा हल किया जाता है। निश्चित नहीं है कि यह मुख्य समस्या है जो op है या कि वाक्यविन्यास भ्रमित है और बहुत से लोग इसे नहीं समझते हैं।
एचएमआर

@HMR, मैं गलत हो सकता हूं, लेकिन मुझे लगता है कि "लेकिन प्रोटोटाइप काफी खतरनाक है" कुख्यात प्रोटोटाइप ढांचे को संदर्भित करता है जो भाषा सुविधा का दुरुपयोग कर सकता हैprototype
बिंकी

प्रोटोटाइपिंग खतरनाक है क्योंकि यदि आप उन वस्तुओं का उपयोग कर रहे हैं जिन्हें आपने नहीं बनाया है, तो आप हमेशा यह नहीं जानते हैं कि उन्हें प्रोटोटाइप के रूप में उपयोग करने के क्या दुष्प्रभाव होंगे। उदाहरण के लिए इस फिडेल को देखें: jsfiddle.net/fo6r20rg
Arkain
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.