javascript - जावास्क्रिप्ट। प्रोटीोटाइप कैसे काम करता है?




prototype-oriented (14)

मैं गतिशील प्रोग्रामिंग भाषाओं में नहीं हूं, लेकिन मैंने जावास्क्रिप्ट कोड का अपना उचित हिस्सा लिखा है। इस प्रोटोटाइप-आधारित प्रोग्रामिंग के आसपास मुझे कभी भी अपना सिर नहीं मिला, क्या कोई यह जानता है कि यह कैसे काम करता है?

var obj = new Object(); // not a functional object
obj.prototype.test = function() { alert('Hello?'); }; // this is wrong!

function MyObject() {} // a first class functional object
MyObject.prototype.test = function() { alert('OK'); } // OK

मुझे कुछ समय पहले लोगों के साथ बहुत सी चर्चा याद है (मुझे बिल्कुल यकीन नहीं है कि मैं क्या कर रहा हूं) लेकिन जैसा कि मैं इसे समझता हूं, कक्षा की कोई अवधारणा नहीं है। यह सिर्फ एक वस्तु है, और उन वस्तुओं के उदाहरण मूल के क्लोन हैं, है ना?

लेकिन जावास्क्रिप्ट में इस .prototype संपत्ति का सही उद्देश्य क्या है? यह वस्तुओं को तत्काल करने से कैसे संबंधित है?

संपादित करें

इन slides ने वास्तव में इस विषय को समझने में बहुत मदद की।


what is the exact purpose of this ".prototype" property?

The interface to standard classes become extensible. For example, you are using the Array class and you also need to add a custom serializer for all your array objects. Would you spend time coding up a subclass, or use composition or ... The prototype property solves this by letting the users control the exact set of members/methods available to a class.

Think of prototypes as an extra vtable-pointer. When some members are missing from the original class, the prototype is looked up at runtime.


इस धागे को पढ़ने के बाद, मुझे जावास्क्रिप्ट प्रोटोटाइप चेन से उलझन में लग रहा है, तो मुझे इन चार्टों को मिला

http://iwiki.readthedocs.org/en/latest/javascript/js_core.html#inheritance

प्रोटोटाइप चेन द्वारा जावास्क्रिप्ट विरासत दिखाने के लिए यह एक स्पष्ट चार्ट है

तथा

http://www.javascriptbank.com/javascript/article/JavaScript_Classical_Inheritance/

इस में कोड और कई अच्छे आरेखों के साथ एक उदाहरण है।

प्रोटोटाइप श्रृंखला अंततः ऑब्जेक्ट.प्रोटोटाइप पर वापस आती है।

प्रोटोटाइप श्रृंखला को तकनीकी रूप से तब तक बढ़ाया जा सकता है जब तक आप चाहते हैं, प्रत्येक बार अभिभावक वर्ग के किसी ऑब्जेक्ट के बराबर उप-वर्ग के प्रोटोटाइप को सेट करके।

उम्मीद है कि जावास्क्रिप्ट प्रोटोटाइप चेन को समझना आपके लिए भी उपयोगी है।


जावास्क्रिप्ट में सामान्य अर्थ में विरासत नहीं है, लेकिन इसमें प्रोटोटाइप श्रृंखला है।

प्रोटोटाइप श्रृंखला

यदि किसी ऑब्जेक्ट का कोई ऑब्जेक्ट ऑब्जेक्ट में नहीं पाया जा सकता है तो यह प्रोटोटाइप श्रृंखला में इसकी तलाश करता है। श्रृंखला में अन्य वस्तुओं का समावेश होता है। दिए गए उदाहरण के प्रोटोटाइप को __proto__ चर के साथ एक्सेस किया जा सकता है। प्रत्येक ऑब्जेक्ट में एक है, क्योंकि जावास्क्रिप्ट में कक्षाओं और उदाहरणों के बीच कोई अंतर नहीं है।

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

यह विरासत के लिए भी उपयोगी है, क्योंकि प्रोटोटाइप श्रृंखला में कई अन्य वस्तुएं हो सकती हैं।


प्रत्येक ऑब्जेक्ट में एक आंतरिक संपत्ति होती है, [[प्रोटोटाइप]], इसे किसी अन्य ऑब्जेक्ट से जोड़ती है:

object [[Prototype]] -> anotherObject

पारंपरिक जावास्क्रिप्ट में, जुड़ा हुआ ऑब्जेक्ट फ़ंक्शन की prototype प्रॉपर्टी है:

object [[Prototype]] -> aFunction.prototype

कुछ वातावरण [[प्रोटोटाइप]] को __proto__ रूप में __proto__ :

anObject.__proto__ === anotherObject

ऑब्जेक्ट बनाते समय आप [[प्रोटोटाइप]] लिंक बनाते हैं।

// (1) Object.create:
var object = Object.create(anotherObject)
// object.__proto__ = anotherObject

// (2) ES6 object initializer:
var object = { __proto__: anotherObject };
// object.__proto__ = anotherObject

// (3) Traditional JavaScript:
var object = new aFunction;
// object.__proto__ = aFunction.prototype

तो ये कथन समकक्ष हैं:

var object = Object.create(Object.prototype);
var object = { __proto__: Object.prototype }; // ES6 only
var object = new Object;

एक new कथन लिंक लक्ष्य ( Object.prototype ) स्वयं नहीं दिखाता है; इसके बजाय लक्ष्य कन्स्ट्रक्टर ( Object ) द्वारा निहित है।

याद है:

  • प्रत्येक ऑब्जेक्ट में एक लिंक होता है, [[प्रोटोटाइप]], कभी-कभी __proto__ रूप में उजागर __proto__
  • प्रत्येक समारोह में prototype संपत्ति होती है।
  • new के साथ बनाए गए ऑब्जेक्ट्स उनके कन्स्ट्रक्टर की prototype प्रॉपर्टी से जुड़े होते हैं।
  • यदि कोई फ़ंक्शन कभी कन्स्ट्रक्टर के रूप में उपयोग नहीं किया जाता है, तो इसकी prototype संपत्ति अप्रयुक्त हो जाएगी।
  • यदि आपको किसी कन्स्ट्रक्टर की आवश्यकता नहीं है, तो new बजाय Object.create उपयोग करें।

यह लेख लंबा है। लेकिन मुझे यकीन है कि यह जावास्क्रिप्ट विरासत की "प्रोटोटाइपिकल" प्रकृति के बारे में आपके अधिकांश प्रश्नों को साफ़ करेगा। और भी अधिक। पूरा लेख पढ़ें।

जावास्क्रिप्ट में मूल रूप से दो प्रकार के डेटा प्रकार होते हैं

  • गैर वस्तुएं
  • वस्तुओं

गैर वस्तुएं

गैर ऑब्जेक्ट डेटा प्रकार निम्नलिखित हैं

  • तार
  • संख्या (NaN और अनंतता सहित)
  • बुलियन मूल्य (सत्य, झूठा)
  • अपरिभाषित

टाइपफ ऑपरेटर का उपयोग करते समय ये डेटा प्रकार निम्नानुसार लौटते हैं

टाइपफ "स्ट्रिंग शाब्दिक" (या स्ट्रिंग अक्षर युक्त एक चर) === 'स्ट्रिंग'

टाइप 5 (या कोई संख्यात्मक शाब्दिक या एक परिवर्तनीय संख्यात्मक शाब्दिक या NaN या infynity ) === 'संख्या'

टाइपोफ सत्य (या गलत या एक चर या सत्य युक्त) === 'बूलियन'

टाइप अप अपरिभाषित (या एक अपरिभाषित चर या एक चर जो अनिर्धारित है ) === 'अपरिभाषित'

स्ट्रिंग , संख्या और बूलियन डेटा प्रकारों को ऑब्जेक्ट्स और गैर ऑब्जेक्ट्स दोनों के रूप में प्रदर्शित किया जा सकता है। जब उन्हें ऑब्जेक्ट्स के रूप में दर्शाया जाता है तो उनका टाइपफ हमेशा === 'ऑब्जेक्ट' होता है। ऑब्जेक्ट डेटा प्रकारों को समझने के बाद हम इस पर वापस आ जाएंगे।

वस्तुओं

ऑब्जेक्ट डेटाटाइप को आगे दो प्रकारों में विभाजित किया जा सकता है

  1. फंक्शन प्रकार ऑब्जेक्ट्स
  2. गैर समारोह प्रकार वस्तुओं

फ़ंक्शन प्रकार ऑब्जेक्ट वे हैं जो टाइपफ़ ऑपरेटर के साथ स्ट्रिंग 'फ़ंक्शन' वापस करते हैं। All the user defined functions and all the JavaScript built in objects that can create new objects by using new operator fall into this category. For eg.

  • Object
  • String
  • Number
  • Boolean
  • Array
  • Typed Arrays
  • RegExp
  • समारोह
  • All the other built in objects that can create new objects by using new operator
  • function UserDefinedFunction (){ /*user defined code */ }

So, typeof(Object) === typeof(String) === typeof(Number) === typeof(Boolean) === typeof(Array) === typeof(RegExp) === typeof(Function) === typeof(UserDefinedFunction) === 'function'

All the Function type objects are actually instances of the built in JavaScript object Function (including the Function object ie it is recursively defined). It is as if the these objects have been defined in the following way

var Object= new Function ([native code for object Object])
var String= new Function ([native code for object String])
var Number= new Function ([native code for object Number])
var Boolean= new Function ([native code for object Boolean])
var Array= new Function ([native code for object Array])
var RegExp= new Function ([native code for object RegExp])
var Function= new Function ([native code  for object Function])
var UserDefinedFunction= new Function ("user defined code")

As mentioned, the Function type objects can further create new objects using the new operator . For eg an object of type Object , String , Number , Boolean , Array , RegExp Or UserDefinedFunction can be created by using

var a=new Object() or var a=Object() or var a={} //Create object of type Object
var a=new String() //Create object of type String
var a=new Number() //Create object of type Number
var a=new Boolean() //Create object of type Boolean
var a=new Array() or var a=Array() or var a=[]  //Create object of type Array
var a=new RegExp() or var a=RegExp() //Create object of type RegExp
var a=new UserDefinedFunction() 

The objects thus created are all Non Function type objects and return their typeof === 'object' . In all these cases the object "a" cannot further create objects using operator new. So the following is wrong

var b=new a() //error. a is not typeof==='function'

The built in object Math is typeof === 'object' . Hence a new object of type Math cannot be created by new operator.

var b=new Math() //error. Math is not typeof==='function'

Also notice that Object , Array and RegExp functions can create a new object without even using operator new . However the follwing ones don't.

var a=String() // Create a new Non Object string. returns a typeof==='string' 
var a=Number() // Create a new Non Object Number. returns a typeof==='number'
var a=Boolean() //Create a new Non Object Boolean. returns a typeof==='boolean'

The user defined functions are special case.

var a=UserDefinedFunction() //may or may not create an object of type UserDefinedFunction() based on how it is defined.

Since the Function type objects can create new objects they are also called Constructors .

Every Constructor/Function (whether built in or user defined) when defined automatically has a property called "prototype" whose value by default is set as an object. This object itself has a property called "constructor" which by default references back the Constructor/Function .

For example when we define a function

function UserDefinedFunction()
{
}

following automatically happens

UserDefinedFunction.prototype={constructor:UserDefinedFunction}

This "prototype" property is only present in the Function type objects (and never in Non Function type objects ).

This is because when a new object is created (using new operator)it inherits all properties and methods from Constructor function's current prototype object ie an internal reference is created in the newly created object that references the object referenced by Constructor function's current prototype object.

This "internal reference" that is created in the object for referencing inherited properties is known as the object's prototype (which references the object referenced by Constructor's "prototype" property but is different from it). For any object (Function or Non Function) this can be retrieved using Object.getPrototypeOf() method. Using this method one can trace the prototype chain of an object.

Also, every object that is created ( Function type or Non Function type ) has a "constructor" property which is inherited from the object referenced by prototype property of the Constructor function. By default this "constructor" property references the Constructor function that created it (if the Constructor Function's default "prototype" is not changed).

For all Function type objects the constructor function is always function Function(){}

For Non Function type objects (eg Javascript Built in Math object) the constructor function is the function that created it. For Math object it is function Object(){} .

All the concept explained above can be a little daunting to understand without any supporting code. Please go through the following code line by line to understand the concept. Try to execute it to have a better understanding.

function UserDefinedFunction()
{ 

} 

/* creating the above function automatically does the following as mentioned earlier

UserDefinedFunction.prototype={constructor:UserDefinedFunction}

*/


var newObj_1=new UserDefinedFunction()

alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype)  //Displays true

alert(newObj_1.constructor) //Displays function UserDefinedFunction

//Create a new property in UserDefinedFunction.prototype object

UserDefinedFunction.prototype.TestProperty="test"

alert(newObj_1.TestProperty) //Displays "test"

alert(Object.getPrototypeOf(newObj_1).TestProperty)// Displays "test"

//Create a new Object

var objA = {
        property1 : "Property1",
        constructor:Array

}


//assign a new object to UserDefinedFunction.prototype
UserDefinedFunction.prototype=objA

alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype)  //Displays false. The object referenced by UserDefinedFunction.prototype has changed

//The internal reference does not change
alert(newObj_1.constructor) // This shall still Display function UserDefinedFunction

alert(newObj_1.TestProperty) //This shall still Display "test" 

alert(Object.getPrototypeOf(newObj_1).TestProperty) //This shall still Display "test"


//Create another object of type UserDefinedFunction
var newObj_2= new UserDefinedFunction();

alert(Object.getPrototypeOf(newObj_2)===objA) //Displays true.

alert(newObj_2.constructor) //Displays function Array()

alert(newObj_2.property1) //Displays "Property1"

alert(Object.getPrototypeOf(newObj_2).property1) //Displays "Property1"

//Create a new property in objA
objA.property2="property2"

alert(objA.property2) //Displays "Property2"

alert(UserDefinedFunction.prototype.property2) //Displays "Property2"

alert(newObj_2.property2) // Displays Property2

alert(Object.getPrototypeOf(newObj_2).property2) //Displays  "Property2"

The prototype chain of every object ultimately traces back to Object.prototype (which itself does not have any prototype object) . Following code can be used for tracing the prototype chain of an object

var o=Starting object;

do {
    alert(o + "\n" + Object.getOwnPropertyNames(o))

}while(o=Object.getPrototypeOf(o))

The prototype chain for various objects work out as follows.

  • Every Function object (including built in Function object)-> Function.prototype -> Object.prototype -> null
  • Simple Objects (created By new Object() or {} including built in Math object)-> Object.prototype -> null
  • Object created with new or Object.create -> One or More prototype chains -> Object.prototype -> null

For creating an object without any prototype use the following:

var o=Object.create(null)
alert(Object.getPrototypeOf(o)) //Displays null

One might think that setting the prototype property of the Constructor to null shall create an object with a null prototype. However in such cases the newly created object's prototype is set to Object.prototype and its constructor is set to function Object. This is demonstrated by the following code

function UserDefinedFunction(){}
UserDefinedFunction.prototype=null// Can be set to any non object value (number,string,undefined etc.)

var o=new UserDefinedFunction()
alert(Object.getPrototypeOf(o)==Object.prototype)   //Displays true
alert(o.constructor)    //Displays Function Object

Following in the summary of this article

  • There are two types of objects Function types and Non Function types
  • Only Function type objects can create a new object using the operator new . The objects thus created are Non Function type objects. The Non Function type objects cannot further create an object using operator new .

  • All Function type objects by default have a "prototype" property. This "prototype" property references an object that has a "constructor" property that by default references the Function type object itself.

  • All objects ( Function type and Non Function type ) have a "constructor" property that by default references the Function type object / Constructor that created it.

  • Every object that gets created internally references the object referenced by "prototype" property of the Constructor that created it. This object is known as the created object's prototype (which is different from Function type objects "prototype" property which it references) . This way the created object can directly access the methods and properties defined in object referenced by the Constructor's "prototype" property (at the time of object creation).

  • An object's prototype (and hence its inherited property names) can be retrieved using the Object.getPrototypeOf() method. In fact this method can be used for navigating the entire prototype chain of the object.

  • The prototype chain of every object ultimately traces back to Object.prototype (Unless the object is created using Object.create(null) in which case the object has no prototype).

  • typeof(new Array())==='object' is by design of language and not a mistake as pointed by Douglas Crockford

  • Setting the prototype property of the Constructor to null(or undefined,number,true,false,string) shall not create an object with a null prototype. In such cases the newly created object's prototype is set to Object.prototype and its constructor is set to function Object.

Hope this helps.



मैं एक जावास्क्रिप्ट शिक्षक के रूप में भूमिका निभाता हूं और जब मैं सिखाता हूं तो प्रोटोटाइप अवधारणा हमेशा कवर करने के लिए एक विवादास्पद विषय रहा है। अवधारणा को स्पष्ट करने के लिए मुझे एक अच्छी विधि के साथ आने में थोड़ी देर लग गई, और अब इस पाठ में मैं यह बताने की कोशिश कर रहा हूं कि जावास्क्रिप्ट कैसे होता है। प्रोटीोटाइप काम करता है।

यह एक बहुत ही सरल प्रोटोटाइप आधारित ऑब्जेक्ट मॉडल है जिसे स्पष्टीकरण के दौरान नमूना के रूप में माना जाएगा, अभी तक कोई टिप्पणी नहीं:

function Person(name){
    this.name = name;
}
Person.prototype.getName = function(){
    console.log(this.name);
}
var person = new Person("George");

प्रोटोटाइप अवधारणा के माध्यम से जाने से पहले हमें कुछ महत्वपूर्ण बिंदुओं पर विचार करना होगा।

1- जावास्क्रिप्ट फ़ंक्शन वास्तव में कैसे काम करते हैं:

पहला कदम उठाने के लिए हमें यह पता लगाना होगा कि जावास्क्रिप्ट फ़ंक्शंस वास्तव में कैसे काम करता है, this श्रेणी का उपयोग करके this तरह के कीवर्ड या फ़ंक्शन के साथ नियमित कार्य के रूप में, यह क्या करता है और यह क्या लौटाता है।

मान लें कि हम एक Person वस्तु मॉडल बनाना चाहते हैं। लेकिन इस चरण में मैं prototype और new कीवर्ड का उपयोग किए बिना वही सटीक चीज़ करने की कोशिश कर रहा हूं।

तो इस चरण में, objects और this कीवर्ड में, हमारे पास सब कुछ है।

पहला सवाल यह होगा कि this कीवर्ड new कीवर्ड का उपयोग किए बिना उपयोगी कैसे हो सकता है

तो जवाब देने के लिए कि मान लें कि हमारे पास एक खाली वस्तु है, और दो कार्य जैसे:

var person = {};
function Person(name){  this.name = name;  }

function getName(){
    console.log(this.name);
}

और अब new कीवर्ड का उपयोग किए बिना हम इन कार्यों का उपयोग कैसे कर सकते हैं। तो जावास्क्रिप्ट को ऐसा करने के 3 अलग-अलग तरीके हैं:

ए। पहला तरीका केवल फ़ंक्शन को नियमित फ़ंक्शन के रूप में कॉल करना है:

Person("George");
getName();//would print the "George" in the console

इस मामले में, यह वर्तमान संदर्भ वस्तु होगी, जो आम तौर पर ब्राउज़र में ग्लोबल window ऑब्जेक्ट या Node.js में GLOBAL है। इसका मतलब है कि हमारे पास ब्राउज़र में window.name होगा, Node.js में GLOBAL.name, "जॉर्ज" के मूल्य के साथ।

ख। हम उन्हें एक वस्तु के रूप में संलग्न कर सकते हैं , इसकी गुणधर्मों के रूप में

- ऐसा करने का सबसे आसान तरीका खाली person वस्तु को संशोधित करना है, जैसे:

person.Person = Person;
person.getName = getName;

इस तरह हम उन्हें कॉल कर सकते हैं:

person.Person("George");
person.getName();// -->"George"

और अब person वस्तु इस तरह है:

Object {Person: function, getName: function, name: "George"}

- किसी ऑब्जेक्ट में किसी संपत्ति को अटैच करने का दूसरा तरीका उस ऑब्जेक्ट के prototype का उपयोग कर रहा है जो किसी भी जावास्क्रिप्ट ऑब्जेक्ट में __proto__ के नाम से __proto__ , और मैंने इसे सारांश भाग पर थोड़ा सा समझाया है। तो हम ऐसा करके समान परिणाम प्राप्त कर सकते हैं:

person.__proto__.Person = Person;
person.__proto__.getName = getName;

लेकिन इस तरह हम वास्तव में क्या कर रहे हैं ऑब्जेक्ट.प्रोटोटाइप को संशोधित कर रहा है, क्योंकि जब भी हम Object.prototype ( { ... } ) का उपयोग करके जावास्क्रिप्ट ऑब्जेक्ट बनाते हैं, तो यह ऑब्जेक्ट.प्रोटोटाइप के आधार पर बनाया जाता है, जिसका अर्थ है कि यह नव निर्मित से जुड़ा हुआ है __proto__ नामक एक विशेषता के रूप में ऑब्जेक्ट करें, इसलिए यदि हम इसे बदलते हैं, जैसा कि हमने अपने पिछले कोड स्निपेट पर किया है, तो सभी जावास्क्रिप्ट ऑब्जेक्ट्स बदल जाएंगे, अच्छे अभ्यास नहीं। तो अब बेहतर अभ्यास क्या हो सकता है:

person.__proto__ = {
    Person: Person,
    getName: getName
};

और अब अन्य वस्तुएं शांति में हैं, लेकिन यह अभी भी एक अच्छा अभ्यास प्रतीत नहीं होता है। तो हमारे पास अभी भी एक और समाधान है, लेकिन इस समाधान का उपयोग करने के लिए हमें उस कोड की उस पंक्ति पर वापस जाना चाहिए जहां person ऑब्जेक्ट बनाया गया था ( var person = {}; ) फिर इसे इस प्रकार बदलें:

var propertiesObject = {
    Person: Person,
    getName: getName
};
var person = Object.create(propertiesObject);

यह एक नया जावास्क्रिप्ट Object और propertiesObject को संलग्न करता है __proto__ विशेषता के लिए। तो यह सुनिश्चित करने के लिए कि आप कर सकते हैं:

console.log(person.__proto__===propertiesObject); //true

लेकिन यहां मुश्किल बात यह है कि आपके पास person वस्तु के पहले स्तर पर __proto__ में परिभाषित सभी गुणों तक पहुंच है (अधिक जानकारी के लिए सारांश भाग पढ़ें)।

जैसा कि आप इन दो तरीकों में से किसी एक का उपयोग करके देखते हैं, this वास्तव में person वस्तु को इंगित करेगा।

सी। जावास्क्रिप्ट के साथ फ़ंक्शन प्रदान करने का एक और तरीका है, जो call का उपयोग कर रहा है या फ़ंक्शन को आमंत्रित apply लिए लागू होता है।

लागू () विधि किसी फ़ंक्शन को दिए गए मान और तर्क के साथ एक सरणी (या एक सरणी जैसी वस्तु) के रूप में प्रदान किया जाता है।

तथा

कॉल () विधि एक फ़ंक्शन को इस मान और दिए गए तर्कों के साथ व्यक्तिगत रूप से प्रदान की जाती है।

इस तरह से मेरा पसंदीदा है, हम आसानी से हमारे कार्यों को कॉल कर सकते हैं जैसे:

Person.call(person, "George");

या

//apply is more useful when params count is not fixed
Person.apply(person, ["George"]);

getName.call(person);   
getName.apply(person);

प्रोप्रोटाइप कार्यक्षमता को समझने के लिए ये 3 विधियां महत्वपूर्ण प्रारंभिक चरण हैं।

2- new कीवर्ड कैसे काम करता है?

.prototype कार्यक्षमता को समझने का यह दूसरा कदम है। .prototype वह प्रक्रिया है जिसका उपयोग मैं प्रक्रिया को अनुकरण करने के लिए करता हूं:

function Person(name){  this.name = name;  }
my_person_prototype = { getName: function(){ console.log(this.name); } };

जब आप new कीवर्ड का उपयोग करते हैं, तो इस भाग में मैं new कीवर्ड और prototype का उपयोग किए बिना जावास्क्रिप्ट को ले जाने वाले सभी चरणों को लेने की कोशिश कर रहा हूं। इसलिए जब हम new Person("George") , तो Person समारोह एक निर्माता के रूप में कार्य करता है, ये जावास्क्रिप्ट करता है, एक-एक करके:

ए। सबसे पहले यह एक खाली वस्तु बनाता है, मूल रूप से एक खाली हैश की तरह:

var newObject = {};

ख। जावास्क्रिप्ट को ले जाने वाला अगला चरण सभी प्रोटोटाइप ऑब्जेक्ट्स को नव निर्मित ऑब्जेक्ट में संलग्न करना है

हमारे पास प्रोटोटाइप ऑब्जेक्ट के समान my_person_prototype है।

for(var key in my_person_prototype){
    newObject[key] = my_person_prototype[key];
}

ऐसा नहीं है कि जावास्क्रिप्ट वास्तव में प्रोटोटाइप में परिभाषित गुणों को जोड़ता है। वास्तविक तरीका प्रोटोटाइप श्रृंखला अवधारणा से संबंधित है।

ए। और बी। इन दो चरणों के बजाय आप एक ही परिणाम कर सकते हैं:

var newObject = Object.create(my_person_prototype);
//here you can check out the __proto__ attribute
console.log(newObject.__proto__ === my_person_prototype); //true
//and also check if you have access to your desired properties
console.log(typeof newObject.getName);//"function"

अब हम getName फ़ंक्शन को हमारे my_person_prototype में कॉल कर सकते हैं:

newObject.getName();

सी। तो यह उस वस्तु को कन्स्ट्रक्टर को देता है,

हम इसे अपने नमूने के साथ कर सकते हैं जैसे:

Person.call(newObject, "George");

या

Person.apply(newObject, ["George"]);

तो कन्स्ट्रक्टर जो कुछ भी चाहता है वह कर सकता है, क्योंकि उस कन्स्ट्रक्टर के अंदर यह वह वस्तु है जो अभी बनाई गई थी।

अब अन्य चरणों को अनुकरण करने से पहले अंतिम परिणाम: ऑब्जेक्ट {नाम: "जॉर्ज"}

सारांश:

असल में, जब आप फ़ंक्शन पर नए कीवर्ड का उपयोग करते हैं, तो आप उस पर कॉल कर रहे हैं और वह फ़ंक्शन एक कन्स्ट्रक्टर के रूप में कार्य करता है, इसलिए जब आप कहते हैं:

new FunctionName()

जावास्क्रिप्ट आंतरिक रूप से एक ऑब्जेक्ट बनाता है, एक खाली हैश और फिर यह उस ऑब्जेक्ट को कन्स्ट्रक्टर को देता है, तो कन्स्ट्रक्टर जो कुछ भी चाहता है वह कर सकता है, क्योंकि उस कन्स्ट्रक्टर के अंदर यह ऑब्जेक्ट है जो अभी बनाया गया था और फिर यह आपको निश्चित रूप से ऑब्जेक्ट देता है अगर आपने अपने फ़ंक्शन में रिटर्न स्टेटमेंट का उपयोग नहीं किया है या यदि आपने return undefined; अपने समारोह शरीर के अंत में।

तो जब जावास्क्रिप्ट किसी ऑब्जेक्ट पर किसी प्रॉपर्टी को देखने के लिए जाता है, तो यह पहली चीज करता है, क्या यह उस ऑब्जेक्ट पर दिखता है। और फिर एक गुप्त संपत्ति [[prototype]] जिसे हम आमतौर पर __proto__ तरह __proto__ और वह संपत्ति है जो जावास्क्रिप्ट को आगे देखती है। और जब यह __proto__ को __proto__ , जहां तक ​​यह एक और जावास्क्रिप्ट ऑब्जेक्ट है, तो इसका अपना __proto__ विशेषता है, यह उस बिंदु तक पहुंच जाता है जब तक कि अगला __proto__ शून्य न हो। बिंदु जावास्क्रिप्ट में एकमात्र वस्तु है कि इसकी __proto__ विशेषता शून्य है Object.prototype ऑब्जेक्ट:

console.log(Object.prototype.__proto__===null);//true

और इस तरह जावास्क्रिप्ट जावास्क्रिप्ट में काम करता है।

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


0) दो अलग-अलग चीजों को "प्रोटोटाइप" कहा जा सकता है:

  • प्रोटोटाइप संपत्ति, obj.prototype में के रूप में

  • प्रोटोटाइप आंतरिक संपत्ति, ईएस 5 में [[Prototype]] रूप में दर्शाया गया है।

    इसे Object.getPrototypeOf() माध्यम से पुनर्प्राप्त किया जा सकता है।

    फ़ायरफ़ॉक्स इसे __proto__ प्रॉपर्टी के माध्यम से विस्तार के रूप में सुलभ बनाता है। ES6 अब __proto__ लिए कुछ वैकल्पिक आवश्यकताओं का उल्लेख करता है

1) प्रश्नों का उत्तर देने के लिए उन अवधारणाएं मौजूद हैं:

जब मैं obj.property करता obj.property , जेएस कहां obj.property है। obj.property ?

सहजता से, शास्त्रीय विरासत संपत्ति लुकअप को प्रभावित करना चाहिए।

2)

  • __proto__ डॉट के लिए प्रयोग किया जाता है . obj.property में संपत्ति लुकअप के रूप में।
  • .prototype का उपयोग सीधे लुकअप के लिए नहीं किया जाता है, केवल अप्रत्यक्ष रूप से क्योंकि यह ऑब्जेक्ट सृजन पर __proto__ को new साथ निर्धारित करता है।

लुकअप ऑर्डर है:

  • obj गुण obj.p = ... या Object.defineProperty(obj, ...) साथ जोड़ा गया
  • obj.__proto__ गुण
  • obj.__proto__.__proto__ , और इसी तरह
  • अगर कुछ __proto__ null , तो undefined वापसी।

यह तथाकथित प्रोटोटाइप श्रृंखला है

आप से बच सकते हैं . obj.hasOwnProperty('key') और Object.getOwnPropertyNames(f) साथ लुकअप

3) obj.__proto__ सेट करने के दो मुख्य तरीके हैं obj.__proto__ :

  • new :

    var F = function() {}
    var f = new F()
    

    तो new सेट है:

    f.__proto__ === F.prototype
    

    यह वह जगह है जहां .prototype उपयोग किया जाता है।

  • Object.create :

     f = Object.create(proto)
    

    सेट:

    f.__proto__ === proto
    

4) कोड:

var F = function() {}
var f = new F()

निम्नलिखित आरेख के अनुरूप है:

(Function)       (  F  )                                      (f)
 |  ^             | | ^                                        |
 |  |             | | |                                        |
 |  |             | | +-------------------------+              |
 |  |constructor  | |                           |              |
 |  |             | +--------------+            |              |
 |  |             |                |            |              |
 |  |             |                |            |              |
 |[[Prototype]]   |[[Prototype]]   |prototype   |constructor   |[[Prototype]]
 |  |             |                |            |              |
 |  |             |                |            |              |
 |  |             |                | +----------+              |
 |  |             |                | |                         |
 |  |             |                | | +-----------------------+
 |  |             |                | | |
 v  |             v                v | v
(Function.prototype)              (F.prototype)
 |                                 |
 |                                 |
 |[[Prototype]]                    |[[Prototype]]
 |                                 |
 |                                 |
 | +-------------------------------+
 | |
 v v
(Object.prototype)
 | | ^
 | | |
 | | +---------------------------+
 | |                             |
 | +--------------+              |
 |                |              |
 |                |              |
 |[[Prototype]]   |constructor   |prototype
 |                |              |
 |                |              |
 |                | -------------+
 |                | |
 v                v |
(null)           (Object)

यह चित्र कई भाषा पूर्वनिर्धारित ऑब्जेक्ट नोड्स दिखाता है: null , Object , Object , Function और Object.prototype । कोड की हमारी 2 लाइनों ने केवल f , F और FF.prototype

5)। .constructor आमतौर पर .constructor से आता है . देखो:

f.constructor === F
!f.hasOwnProperty('constructor')
Object.getPrototypeOf(f) === F.prototype
F.prototype.hasOwnProperty('constructor')
F.prototype.constructor === f.constructor

जब हम f.constructor , जावास्क्रिप्ट करता है . के रूप में देखो:

  • f नहीं है। .constructor
  • f.__proto__ === F.prototype में .constructor === F , इसलिए इसे लें

नतीजा f.constructor == F सहजता से सही है, क्योंकि F का निर्माण F लिए किया जाता है, उदाहरण के लिए सेट फ़ील्ड, क्लासिक ओओपी भाषाओं की तरह।

6) शास्त्रीय विरासत वाक्यविन्यास प्रोटोटाइप श्रृंखला में हेरफेर करके हासिल किया जा सकता है।

ES6 class जोड़ता है और कीवर्ड extends है, जो पहले संभव प्रोटोटाइप हेरफेर पागलपन के लिए सिंटैक्स चीनी है।

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:
// http://.com/questions/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

Consider the following keyValueStore object :

var keyValueStore = (function() {
    var count = 0;
    var kvs = function() {
        count++;
        this.data = {};
        this.get = function(key) { return this.data[key]; };
        this.set = function(key, value) { this.data[key] = value; };
        this.delete = function(key) { delete this.data[key]; };
        this.getLength = function() {
            var l = 0;
            for (p in this.data) l++;
            return l;
        }
    };

    return  { // Singleton public properties
        'create' : function() { return new kvs(); },
        'count' : function() { return count; }
    };
})();

I can create a new instance of this object by doing this :

kvs = keyValueStore.create();

Each instance of this object would have the following public properties :

  • data
  • get
  • set
  • delete
  • getLength

Now, suppose we create 100 instances of this keyValueStore object. Even though get , set , delete , getLength will do the exact same thing for each of these 100 instances, every instance has its own copy of this function.

Now, imagine if you could have just a single get , set , delete and getLength copy, and each instance would reference that same function. This would be better for performance and require less memory.

That's where prototypes come in. A prototype is a "blueprint" of properties that is inherited but not copied by instances. So this means that it exists only once in memory for all instances of an object and is shared by all of those instances.

Now, consider the keyValueStore object again. I could rewrite it like this :

var keyValueStore = (function() {
    var count = 0;
    var kvs = function() {
        count++;
        this.data = {};
    };

    kvs.prototype = {
        'get' : function(key) { return this.data[key]; },
        'set' : function(key, value) { this.data[key] = value; },
        'delete' : function(key) { delete this.data[key]; },
        'getLength' : function() {
            var l = 0;
            for (p in this.data) l++;
            return l;
        }
    };

    return  {
        'create' : function() { return new kvs(); },
        'count' : function() { return count; }
    };
})();

This does EXACTLY the same as the previous version of the keyValueStore object, except that all of its methods are now put in a prototype. What this means, is that all of the 100 instances now share these four methods instead of each having their own copy.


I always like analogies when it comes to understand this type of stuff. 'Prototypical inheritance' is pretty confusing in comparison to class bass inheritance in my opinion, even though prototypes are much simpler paradigm. In fact with prototypes, there really is no inheritance, so the name in and of itself misleading, it's more a type of 'delegation'.

Imagine this ....

You're in high-school, and you're in class and have a quiz that's due today, but you don't have a pen to fill out your answers. Doh!

You're sitting next to your friend Finnius, who might have a pen. You ask, and he looks around his desk unsuccessfully, but instead of saying "I don't have a pen", he's a nice friend he checks with his other friend Derp if he has a pen. Derp does indeed have a spare pen and passes it back to Finnius, who passes it over to you to complete your quiz. Derp has entrusted the pen to Finnius, who has delegated the pen to you for use.

What is important here is that Derp does not give the pen to you, as you don't have a direct relationship with him.

This, is a simplified example of how prototypes work, where a tree of data is searched for the thing you're looking for.


It may help to categorise prototype chains into two categories.

Consider the constructor:

 function Person() {}

The value of Object.getPrototypeOf(Person) is a function. In fact, it is Function.prototype . Since Person was created as a function, it shares the same prototype function object that all functions have. It is the same as Person.__proto__ , but that property should not be used. Anyway, with Object.getPrototypeOf(Person) you effectively walk up the ladder of what is called the prototype chain.

The chain in upward direction looks like this:

PersonFunction.prototypeObject.prototype (end point)

Important is that this prototype chain has little to do with the objects that Person can construct . Those constructed objects have their own prototype chain, and this chain can potentially have no close ancestor in common with the one mentioned above.

Take for example this object:

var p = new Person();

p has no direct prototype-chain relationship with Person . Their relationship is a different one. The object p has its own prototype chain. Using Object.getPrototypeOf , you'll find the chain is as follows:

pPerson.prototypeObject.prototype (end point)

There is no function object in this chain (although that could be).

So Person seems related to two kinds of chains, which live their own lives. To "jump" from one chain to the other, you use:

  1. .prototype : jump from the constructor's chain to the created-object's chain. This property is thus only defined for function objects (as new can only be used on functions).

  2. .constructor : jump from the created-object's chain to the constructor's chain.

Here is a visual presentation of the two prototype chains involved, represented as columns:

To summarise:

The prototype property gives no information of the subject's prototype chain, but of objects created by the subject.

It is no surprise that the name of the property prototype can lead to confusion. It would maybe have been clearer if this property had been named prototypeOfConstructedInstances or something along that line.

You can jump back and forth between the two prototype chains:

Person.prototype.constructor === Person

This symmetry can be broken by explicitly assigning a different object to the prototype property (more about that later).

Create one Function, Get Two Objects

Person.prototype is an object that was created at the same time the function Person was created. It has Person as constructor, even though that constructor did not actually execute yet. So two objects are created at the same time:

  1. The function Person itself
  2. The object that will act as prototype when the function is called as a constructor

Both are objects, but they have different roles: the function object constructs , while the other object represents the prototype of any object that function will construct. The prototype object will become the parent of the constructed object in its prototype chain.

Since a function is also an object, it also has its own parent in its own prototype chain, but recall that these two chains are about different things.

Here are some equalities that could help grasp the issue -- all of these print true :

function Person() {};

// This is prototype chain info for the constructor (the function object):
console.log(Object.getPrototypeOf(Person) === Function.prototype);
// Step further up in the same hierarchy:
console.log(Object.getPrototypeOf(Function.prototype) === Object.prototype);
console.log(Object.getPrototypeOf(Object.prototype) === null);
console.log(Person.__proto__ === Function.prototype);
// Here we swap lanes, and look at the constructor of the constructor
console.log(Person.constructor === Function);
console.log(Person instanceof Function);

// Person.prototype was created by Person (at the time of its creation)
// Here we swap lanes back and forth:
console.log(Person.prototype.constructor === Person);
// Although it is not an instance of it:
console.log(!(Person.prototype instanceof Person));
// Instances are objects created by the constructor:
var p = new Person();
// Similarly to what was shown for the constructor, here we have
// the same for the object created by the constructor:
console.log(Object.getPrototypeOf(p) === Person.prototype);
console.log(p.__proto__ === Person.prototype);
// Here we swap lanes, and look at the constructor
console.log(p.constructor === Person);
console.log(p instanceof Person);

Adding levels to the prototype chain

Although a prototype object is created when you create a constructor function, you can ignore that object, and assign another object that should be used as prototype for any subsequent instances created by that constructor.

For instance:

function Thief() { }
var p = new Person();
Thief.prototype = p; // this determines the prototype for any new Thief objects:
var t = new Thief();

Now the prototype chain of t is one step longer than that of p :

tpPerson.prototypeObject.prototype (end point)

The other prototype chain is not longer: Thief and Person are siblings sharing the same parent in their prototype chain:

Person }
Thief } → Function.prototypeObject.prototype (end point)

The earlier presented graphic can then be extended to this (the original Thief.prototype is left out):

The blue lines represent prototype chains, the other coloured lines represent other relationships:

  • between an object and its constructor
  • between a constructor and the prototype object that will be used for constructing objects

Let me tell you my understanding of prototypes. I am not going to compare the inheritance here with other languages. I wish people would stop comparing languages, and just understand the language as itself. Understanding prototypes and prototypal inheritance is so simple, as I will show you below.

Prototype is like a model, based on which you create a product. The crucial point to understand is that when you create an object using another object as it's prototype, the link between the prototype and the product is ever-lasting. For instance:

var model = {x:2};
var product = Object.create(model);
model.y = 5;
product.y
=>5

Every object contains an internal property called the [[prototype]], which can be accessed by the Object.getPrototypeOf() function. Object.create(model) creates a new object and sets it's [[prototype]] property to the object model . Hence when you do Object.getPrototypeOf(product) , you will get the object model .

Properties in the product are handled in the following way:

  • When a property is accessed to just read it's value, its looked up in the scope chain. The search for the variable starts from the product upwards to it's prototype. If such a variable is found in the search, the search is stopped right there, and the value is returned. If such a variable cannot be found in the scope chain, undefined is returned.
  • When a property is written(altered), then the property is always written on the product object. If the product does not have such a property already, it is implicitly created and written.

Such a linking of objects using the prototype property is called prototypal inheritance. There, it is so simple, agree?


There's two distinct but related entities here that need explaining:

  • The .prototype property of functions.
  • The [[Prototype]] [1] property of all objects [2] .

These are two different things.

The [[Prototype]] property:

This is a property that exists on all [2] objects.

What's stored here is another object, which, as an object itself, has a [[Prototype]] of its own that points to another object. That other object has a [[Prototype]] of its own. This story continues until you reach the prototypical object that provides methods that are accessible on all objects (like .toString ).

The [[Prototype]] property is part of what forms the [[Prototype]] chain. This chain of [[Prototype]] objects is what is examined when, for example, [[Get]] or [[Set]] operations are performed on an object:

var obj = {}
obj.a         // [[Get]] consults prototype chain
obj.b = 20    // [[Set]] consults prototype chain

The .prototype property:

This is a property that is only found on functions. Using a very simple function:

function Bar(){};

The .prototype property holds an object that will be assigned to b.[[Prototype]] when you do var b = new Bar . You can easily examine this:

// Both assign Bar.prototype to b1/b2[[Prototype]]
var b = new Bar;
// Object.getPrototypeOf grabs the objects [[Prototype]]
console.log(Object.getPrototypeOf(b) === Bar.prototype) // true

One of the most important .prototype s is that Object.prototype . This prototype holds the prototypical object that all [[Prototype]] chains contain. On it, all the available methods for new objects are defined:

// Get properties that are defined on this object
console.log(Object.getOwnPropertyDescriptors(Object.prototype))

Now, since .prototype is an object, it has a [[Prototype]] property. When you don't make any assignments to Function.prototype , the .prototype 's [[Prototype]] points to the prototypical object ( Object.prototype ). This is automatically performed anytime you create a new function.

This way, any time you do new Bar; the prototype chain is set up for you, you get everything defined on Bar.prototype and everything defined on Object.prototype :

var b = new Bar;
// Get all Bar.prototype properties
console.log(b.__proto__ === Bar.prototype)
// Get all Object.prototype properties
console.log(b.__proto__.__proto__ === Object.prototype)

When you do make assignments to Function.prototype all you are doing is extending the prototype chain to include another object. It's like an insertion in a singly linked list.

This basically alters the [[Prototype]] chain allowing properties that are defined on the object assigned to Function.prototype to be seen by any object created by the function.

[1: वह किसी को भ्रमित नहीं करेगा; माध्यम से उपलब्ध कराया संपत्ति कई कार्यान्वयन में। __proto__
[2]: सभी को छोड़कर null


When a constructor creates an object, that object implicitly references the constructor's “prototype” property for the purpose of resolving property references. The constructor's “prototype” property can be referenced by the program expression constructor.prototype, and properties added to an object's prototype are shared, through inheritance, by all objects sharing the prototype.






prototype-oriented