Vraag Hoe werkt JavaScript .prototype?


Ik ben niet zo dol op dynamische programmeertalen, maar ik heb mijn deel van JavaScript-code geschreven. Ik heb nooit echt mijn hoofd rond deze prototype-gebaseerde programmering gestaan, weet iemand hoe dit werkt?

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

Ik herinner me nog een lange discussie die ik een tijdje geleden met mensen had gehad (ik weet niet precies wat ik doe) maar zoals ik het begrijp, is er geen concept van een klasse. Het is maar een object en exemplaren van die objecten zijn klonen van het origineel, toch?

Maar wat is precies het doel hiervan .prototype onroerend goed in JavaScript? Hoe verhoudt het zich tot instanterende objecten?


Bewerk

Deze slides heeft echt veel geholpen om dit onderwerp te begrijpen.


1856
2018-02-21 12:31


oorsprong


antwoorden:


Elk JavaScript-object heeft een interne eigenschap genaamd [[Prototype]]. Als u een woning opzoekt via obj.propName of obj['propName'] en het object heeft niet zo'n eigenschap - die kan worden gecontroleerd via obj.hasOwnProperty('propName') - de runtime zoekt in plaats daarvan naar de eigenschap in het object waarnaar wordt verwezen door [[Prototype]]. Als het prototype-object ook niet zo'n eigenschap heeft, wordt het prototype om de beurt gecontroleerd, zodat het originele object wordt gelopen prototype-chain totdat een overeenkomst is gevonden of het einde is bereikt.

Sommige JavaScript-implementaties bieden directe toegang tot de eigenschap [[Prototype]], bijvoorbeeld via een niet-standaard eigenschap met de naam __proto__. Over het algemeen is het alleen mogelijk om het prototype van een object in te stellen tijdens het maken van een object: als u een nieuw object maakt via new Func(), de eigenschap [[Prototype]] van het object wordt ingesteld op het object waarnaar wordt verwezen door Func.prototype.

Dit maakt het mogelijk klassen in JavaScript te simuleren, hoewel het overervingssysteem van JavaScript - zoals we hebben gezien - prototypisch is en niet op klassen gebaseerd:

Denk maar aan constructor functies als klassen en de eigenschappen van het prototype (dat wil zeggen van het object waarnaar wordt verwezen door de constructor-functie's prototype eigenschap) als gedeelde leden, dwz leden die voor elke instantie hetzelfde zijn. In op klassen gebaseerde systemen worden methoden op dezelfde manier geïmplementeerd voor elke instantie, dus worden de methoden normaal toegevoegd aan het prototype, terwijl de velden van een object systeemspecifiek zijn en daarom tijdens de constructie aan het object zelf worden toegevoegd.


925
2018-02-21 13:33



In een taal die klassieke overerving zoals Java, C # of C ++ implementeert, begin je met het maken van een klasse - een blauwdruk voor je objecten - en dan kun je nieuwe objecten uit die klasse maken of kun je de klasse uitbreiden, een nieuwe klasse definiëren die augments de originele klasse.

In JavaScript maak je eerst een object aan (er bestaat geen concept van klasse), dan kun je je eigen object vergroten of er nieuwe objecten van maken. Het is niet moeilijk, maar een beetje vreemd en moeilijk te metaboliseren voor iemand die gewend is aan de klassieke manier.

Voorbeeld:

//Define a functional object to hold persons in JavaScript
var Person = function(name) {
  this.name = name;
};

//Add dynamically to the already defined object a new getter
Person.prototype.getName = function() {
  return this.name;
};

//Create a new object of type Person
var john = new Person("John");

//Try the getter
alert(john.getName());

//If now I modify person, also John gets the updates
Person.prototype.sayMyName = function() {
  alert('Hello, my name is ' + this.getName());
};

//Call the new method on john
john.sayMyName();

Tot nu toe heb ik het basisobject uitgebreid, nu maak ik een ander object en ervaar ik het van Persoon.

//Create a new object of type Customer by defining its constructor. It's not 
//related to Person for now.
var Customer = function(name) {
    this.name = name;
};

//Now I link the objects and to do so, we link the prototype of Customer to 
//a new instance of Person. The prototype is the base that will be used to 
//construct all new instances and also, will modify dynamically all already 
//constructed objects because in JavaScript objects retain a pointer to the 
//prototype
Customer.prototype = new Person();     

//Now I can call the methods of Person on the Customer, let's try, first 
//I need to create a Customer.
var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();

//If I add new methods to Person, they will be added to Customer, but if I
//add new methods to Customer they won't be added to Person. Example:
Customer.prototype.setAmountDue = function(amountDue) {
    this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function() {
    return this.amountDue;
};

//Let's try:       
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());

var Person = function (name) {
    this.name = name;
};
Person.prototype.getName = function () {
    return this.name;
};
var john = new Person("John");
alert(john.getName());
Person.prototype.sayMyName = function () {
    alert('Hello, my name is ' + this.getName());
};
john.sayMyName();
var Customer = function (name) {
    this.name = name;
};
Customer.prototype = new Person();

var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();
Customer.prototype.setAmountDue = function (amountDue) {
    this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function () {
    return this.amountDue;
};
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());

Hoewel ik gezegd heb dat ik setAmountDue (), getAmountDue () niet op een persoon kan aanroepen.

//The following statement generates an error.
john.setAmountDue(1000);

1755
2018-01-24 03:42



Ik speel een rol als JavaScript-docent en het prototype-concept is altijd al een controversieel onderwerp geweest dat ik tijdens mijn les kon behandelen. Het kostte me een tijdje om een ​​goede methode te bedenken om het concept te verduidelijken, en nu zal ik in deze tekst proberen uit te leggen hoe JavaScript .prototype werkt.


Dit is een heel eenvoudig prototype gebaseerd objectmodel dat tijdens de uitleg als een voorbeeld zou worden beschouwd, zonder commentaar:

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

Er zijn enkele cruciale punten die we moeten overwegen voordat we het prototype concept doornemen.

1- Hoe JavaScript-functies werken:

Om de eerste stap te zetten, moeten we uitzoeken hoe JavaScript-functies werken, als een klasse-achtige functie this zoekwoord erin of gewoon als een reguliere functie met zijn argumenten, wat het doet en wat het oplevert.

Laten we zeggen dat we een willen maken Person objectmodel. maar in deze stap zal ik proberen doe precies hetzelfde zonder te gebruiken prototype en new trefwoord.

Dus in deze stap functions, objects en this sleutelwoord, zijn alles wat we hebben.

De eerste vraag zou zijn hoe this sleutelwoord zou nuttig kunnen zijn zonder het te gebruiken new trefwoord.

Dus om dat te beantwoorden, laten we zeggen dat we een leeg object hebben en twee functies zoals:

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

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

en nu zonder te gebruiken new trefwoord hoe we deze functies kunnen gebruiken. Dus JavaScript heeft 3 verschillende manieren om dat te doen:

een. eerste manier is gewoon om de functie als een reguliere functie te noemen:

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

in dit geval zou dit het huidige contextobject zijn, dat gewoonlijk het globale is window object in de browser of GLOBAL in Node.js. Dit betekent dat we window.name in browser of GLOBAL.name in Node.js zouden hebben, met "George" als waarde.

b. We kunnen hechten naar een object, als zijn eigenschappen

-De makkelijkste manier om dit te doen, wijzig je het lege person object, zoals:

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

op deze manier kunnen we ze noemen:

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

en nu de person object is als:

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

-De andere manier om een ​​eigendom te bevestigen naar een object gebruikt de prototype van dat object dat kan worden gevonden in een JavaScript-object met de naam van __proto__en ik heb geprobeerd het een beetje uit te leggen over het samenvattingsgedeelte. Dus we zouden het vergelijkbare resultaat kunnen krijgen door te doen:

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

Maar op deze manier is wat we eigenlijk aan het doen zijn het aanpassen van de Object.prototype, omdat wanneer we een JavaScript-object maken met behulp van letterlijke tekens ({ ... }), wordt het gemaakt op basis van Object.prototype, wat betekent dat het als een attribuut met het nieuw gecreëerde object verbonden wordt __proto__ , dus als we het veranderen, zoals we in ons vorige codefragment hebben gedaan, zouden alle JavaScript-objecten worden gewijzigd, geen goede gewoonte. Dus wat kan nu de betere praktijk zijn:

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

en nu zijn andere objecten in vrede, maar het lijkt nog steeds geen goede gewoonte. Dus we hebben nog een oplossing, maar om deze oplossing te gebruiken, moeten we teruggaan naar die regel met code person object is gemaakt (var person = {};) verander het dan als volgt:

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

wat het doet is het maken van een nieuw JavaScript Object en bevestig de propertiesObject naar de __proto__ attribuut. Dus om te zorgen dat u het volgende kunt doen:

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

Maar het lastige punt hier is dat je toegang hebt tot alle eigenschappen die zijn gedefinieerd in __proto__ op het eerste niveau van de person object (lees het samenvattinggedeelte voor meer informatie).


zoals je ziet met een van deze twee richtingen this zou precies naar de person voorwerp.

c. JavaScript heeft een andere manier om de functie te voorzien this, die gebruikt telefoontje of van toepassing zijn om de functie aan te roepen.

De methode apply () roept een functie aan met een gegeven waarde en   argumenten opgegeven als een array (of een array-achtig object).

en

De methode call () roept een functie aan met een gegeven waarde en   argumenten afzonderlijk verstrekt.

op deze manier, die mijn favoriet is, kunnen we gemakkelijk onze functies noemen zoals:

Person.call(person, "George");

of

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

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

deze 3 methoden zijn de belangrijke eerste stappen om de .prototype-functionaliteit te achterhalen.


2- Hoe werkt de new sleutelwoord werkt?

dit is de tweede stap om het te begrijpen .prototype functionaliteit. Dit is wat ik gebruik om het proces te simuleren:

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

in dit deel ga ik proberen alle stappen te nemen die JavaScript neemt, zonder de new zoekwoord en prototype, wanneer je gebruikt new trefwoord. dus wanneer we doen new Person("George"), Person function dient als een constructor. Dit is wat JavaScript doet, één voor één:

een. het maakt in de eerste plaats een leeg voorwerp, in feite een lege hash zoals:

var newObject = {};

b. de volgende stap die JavaScript neemt, is om hechten de alle prototypeobjecten van het nieuw gemaakte object

we hebben my_person_prototype hier vergelijkbaar met het prototype-object.

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

Het is niet de manier waarop JavaScript de eigenschappen die in het prototype zijn gedefinieerd, daadwerkelijk koppelt. De feitelijke manier is gerelateerd aan het prototype ketenconcept.


een. & b. In plaats van deze twee stappen kun je exact hetzelfde resultaat hebben door te doen:

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"

nu kunnen we de getName functie in onze my_person_prototype:

newObject.getName();

c. dan geeft het dat object aan de constructeur,

we kunnen dit doen met onze sample zoals:

Person.call(newObject, "George");

of

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

dan kan de constructeur doen wat hij wil, want deze binnenkant van die constructor is het object dat zojuist is gemaakt.

nu het eindresultaat voor het simuleren van de andere stappen:     Object {name: "George"}


Overzicht:

Kortom, wanneer u de nieuwe sleutelwoord op een functie, u roept dat op en die functie dient als een constructeur, dus wanneer u zegt:

new FunctionName()

Javascript maakt intern een object, een lege hash en dan geeft het dat object aan de constructeur, dan kan de constructeur doen wat hij wil, omdat deze binnenkant van die constructor is het object dat zojuist is gemaakt en dan geeft het je dat object natuurlijk als je de return-instructie niet hebt gebruikt in je functie of als je een return undefined; aan het einde van je functielichaam.

Dus wanneer JavaScript een eigenschap op een object gaat opzoeken, is het eerste dat het opzoekt, het op dat object. En dan is er een geheim bezit [[prototype]] waar we meestal het hebben __proto__ en die eigenschap is waar JavaScript naar kijkt. En wanneer het door de __proto__, voor zover het weer een ander JavaScript-object is, heeft het een eigen object __proto__attribuut, het gaat omhoog en omhoog totdat het op het punt komt waarop het volgende __proto__ is niets. Het punt is het enige object in JavaScript dat het is __proto__ attribuut is null is Object.prototype voorwerp:

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

en zo werkt overerving in JavaScript.

The prototype chain

Met andere woorden, wanneer u een prototype-eigenschap op een functie hebt en u een nieuwe aanroept, nadat JavaScript is voltooid met kijken naar dat nieuw gemaakte object voor eigenschappen, zal het gaan kijken naar de functie's .prototype en ook is het mogelijk dat dit object zijn eigen interne prototype heeft. enzovoort.


162
2018-02-13 19:32



prototype kunt u lessen maken. als je het niet gebruikt prototype dan wordt het een statisch.

Hier is een kort voorbeeld.

var obj = new Object();
obj.test = function() { alert('Hello?'); };

In het bovenstaande geval heeft u een statische funcation call-test. Deze functie is alleen toegankelijk via obj.test, waar je obj kunt voorstellen om een ​​klas te zijn.

waar als in de onderstaande code

function obj()
{
}

obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();

De obj is een klasse geworden die nu kan worden geïnstantieerd. Meerdere exemplaren van obj kunnen bestaan ​​en ze hebben allemaal de test functie.

Het bovenstaande is mijn begrip. Ik maak er een community-wiki van, zodat mensen me kunnen corrigeren als ik het mis heb.


66
2017-11-07 09:48



Na het lezen van deze thread, voel ik me in de war met JavaScript Prototype Chain, toen vond ik deze grafieken

http://iwiki.readthedocs.org/en/latest/javascript/js_core.html#inheritance *[[protytype]]* and <code>prototype</code> property of function objects

het is een duidelijke grafiek om JavaScript-overerving door prototypeketen te tonen

en

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

deze bevat een voorbeeld met code en verschillende mooie diagrammen.

prototypeketen valt uiteindelijk terug naar Object.prototype.

prototypeketen kan technisch zo lang worden uitgebreid als u wilt, telkens door het prototype van de subklasse gelijk te stellen aan een object van de bovenliggende klasse.

Ik hoop dat het ook nuttig voor je is om JavaScript Prototype Chain te begrijpen.


59
2018-05-26 20:40



De zeven Koans van het prototype

Toen Ciro San de berg Vuurvos afdaalde na diepe meditatie, was zijn geest helder en vredig.

Zijn hand was echter rusteloos en pakte op zichzelf een penseel en noteerde de volgende aantekeningen.


0) Twee verschillende dingen kunnen "prototype" worden genoemd:

  • de prototype-eigenschap, zoals in obj.prototype

  • de interne eigenschap van het prototype, aangeduid als [[Prototype]]  in ES5.

    Het kan worden opgehaald via de ES5 Object.getPrototypeOf().

    Firefox maakt het toegankelijk via de __proto__ eigendom als een extensie. ES6 vermeldt nu enkele optionele vereisten voor __proto__.


1) Die concepten bestaan ​​om de vraag te beantwoorden:

Wanneer ik het doe obj.property, waar zoekt JS naar .property?

Intuïtief zou klassieke overerving van invloed moeten zijn op het opzoeken van eigendommen.


2)

  • __proto__ wordt gebruikt voor de punt . eigendom opzoeken als in obj.property.
  • .prototype is niet gebruikt voor het direct opzoeken, alleen indirect zoals het bepaalt __proto__ bij het maken van objecten met new.

Opzoekvolgorde is:

  • obj eigenschappen toegevoegd met obj.p = ... of Object.defineProperty(obj, ...)
  • eigenschappen van obj.__proto__
  • eigenschappen van obj.__proto__.__proto__, enzovoort
  • als iets __proto__ is null, terug undefined.

Dit is de zogenaamde prototypeketting.

Je kunt vermijden . opzoeken met obj.hasOwnProperty('key') en Object.getOwnPropertyNames(f)


3) Er zijn twee manieren om in te stellen obj.__proto__:

  • new:

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

    dan new heeft gezet:

    f.__proto__ === F.prototype
    

    Deze is waar .prototype wordt gebruikt.

  • Object.create:

     f = Object.create(proto)
    

    sets:

    f.__proto__ === proto
    

4) De code:

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

Komt overeen met het volgende diagram:

(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)

Dit diagram toont veel taal vooraf gedefinieerde objectknooppunten: null, Object, Object.prototype, Function en Function.prototype. Onze 2 regels code zijn alleen gemaakt f, F en F.prototype.


5)  .constructor komt normaal van F.prototype door het . opzoeken:

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

Wanneer we schrijven f.constructor, JavaScript doet het . opzoeken als:

  • f heeft geen .constructor
  • f.__proto__ === F.prototype heeft .constructor === F, Dus neem het

Het resultaat f.constructor == F is intuïtief correct, sinds F wordt gebruikt om te bouwen fb.v. stel velden in, net zoals in klassieke OOP-talen.


6) Klassieke overerving-syntaxis kan worden bereikt door prototypeketens te manipuleren.

ES6 voegt de class en extends sleutelwoorden, die eenvoudig syntaxisuiker voor eerder mogelijke manipulatie gekte prototype zijn.

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://stackoverflow.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

Vereenvoudigd diagram zonder alle vooraf gedefinieerde objecten:

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

57
2018-06-18 19:48



Elk object heeft een interne eigenschap, [[Prototype]], en koppelt het aan een ander object:

object [[Prototype]] -> anotherObject

In traditioneel javascript is het gekoppelde object het prototype eigenschap van een functie:

object [[Prototype]] -> aFunction.prototype

In sommige omgevingen wordt [[Prototype]] als weergegeven __proto__:

anObject.__proto__ === anotherObject

U maakt de [[Prototype]] -link wanneer u een object maakt.

// (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

Dus deze verklaringen zijn equivalent:

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

EEN new statement toont niet het linkdoel (Object.prototype) zelf; in plaats daarvan wordt het doel geïmpliceerd door de constructeur (Object).

Onthouden:

  • Elk object heeft een link, [[Prototype]], soms belicht als __proto__.
  • Elke functie heeft een prototype eigendom.
  • Objecten gemaakt met new zijn gekoppeld aan de prototype eigendom van hun constructeur.
  • Als een functie nooit als een constructor wordt gebruikt, is het prototype eigendom zal ongebruikt blijven.
  • Als u geen constructor nodig heeft, gebruik dan Object.create in plaats van new.

33
2018-02-21 12:41



Javascript heeft geen overerving in de gebruikelijke betekenis, maar het heeft de prototypeketen.

prototypeketting

Als een lid van een object niet in het object kan worden gevonden, zoekt het ernaar in de prototypeketen. De ketting bestaat uit andere objecten. Het prototype van een bepaald exemplaar kan worden geopend met de __proto__ variabel. Elk object heeft er één, omdat er geen verschil is tussen klassen en instanties in javascript.

Het voordeel van het toevoegen van een functie / variabele aan het prototype is dat het maar één keer in het geheugen moet zijn, niet voor elke instantie.

Het is ook handig voor overerving, omdat de prototypeketen uit vele andere objecten kan bestaan.


23
2017-11-04 14:08



Dit artikel is lang. Maar ik weet zeker dat het de meeste van uw vragen zal wissen met betrekking tot de "prototypische" aard van JavaScript-overerving. En nog meer. Lees alstublieft het volledige artikel.

JavaScript heeft in principe twee soorten gegevenstypen

  • Niet-objecten 
  • Voorwerpen

Niet-objecten

Hierna volgen de Niet-object gegevenstypes

  • draad
  • nummer (inclusief NaN en Infinity)
  • boolean-waarden (true, false) 
  • onbepaald

Deze gegevenstypen worden als volgt weergegeven wanneer u de soort van operator

soort van  "tekenreeks letterlijk" (of een variabele die de tekenreeks letterlijk bevat) === 'draad'

soort van  5 (of een numerieke letterlijke of een variabele met numerieke letterlijke of NaN of Infynity) === 'aantal'

soort van  waar (of vals of een variabele met waar of vals) === 'Boolean'

soort van  onbepaald (of een ongedefinieerde variabele of een variabele die bevat onbepaald) === 'Undefined'

De draad,aantal en boolean gegevenstypen kunnen beide worden weergegeven als Voorwerpen en Niet-objecten.Wanneer ze als objecten worden weergegeven, is hun type altijd === 'object'. We komen hier op terug zodra we de objectgegevenstypen hebben begrepen.

Voorwerpen

De object-datatypes kunnen verder in twee typen worden verdeeld

  1. Functie type objecten
  2. Niet-functionele type objecten

De Functie type objecten zijn degenen die de string retourneren 'functie' met soort van operator. Alle door de gebruiker gedefinieerde functies en alle JavaScript-ingebouwde objecten die nieuwe objecten kunnen maken met behulp van een nieuwe operator vallen in deze categorie. Voor bijvoorbeeld.

  • Voorwerp
  • Draad 
  • Aantal 
  • Boolean
  • reeks 
  • Getypeerde reeksen
  • RegExp
  • Functie 
  • Alle andere ingebouwde objecten die nieuwe objecten kunnen maken met behulp van de nieuwe operator
  • functie  UserDefinedFunction() {/ * door gebruiker gedefinieerde code * /}

Zo, typeof (Object) === typeof (String) === typeof (Number) === typeof (Boolean) === typeof (Array)  === typeof (RegExp) === typeof (Functie)  === typeof (UserDefinedFunction) === 'functie'

Al de Functie type objecten zijn in feite instanties van het ingebouwde JavaScript-object Functie (inclusief de Functie object, d.w.z. het is recursief gedefinieerd). Het is alsof deze objecten op de volgende manier zijn gedefinieerd

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")

Zoals vermeld, de Functie type objecten kan verder nieuwe objecten maken met behulp van de nieuwe operator. Voor bijvoorbeeld een object van het type Voorwerp, Draad, Aantal, Boolean, reeks, RegExp  Of UserDefinedFunction kan worden gemaakt met behulp van

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() 

De aldus gecreëerde objecten zijn alles Niet-functionele type objecten en breng hun terug soort van==='voorwerp'. In al deze gevallen kan het object "a" niet verder creëren objecten met operator nieuw. Dus het volgende is verkeerd

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

Het ingebouwde object Wiskunde is soort van==='voorwerp'. Daarom kan een nieuw object van het type Math niet door de nieuwe operator worden gemaakt.

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

Merk dat ook op Voorwerp,reeks en RegExp functies kunnen een nieuw object maken zonder zelfs te gebruiken operator nieuw. De volgende doen dat echter niet.

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'

De door de gebruiker gedefinieerde functies zijn speciaal geval.

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

Sinds de Functie type objecten kan nieuwe objecten maken die ze ook worden genoemd constructors.

elk Constructor / functie (ongeacht of deze is ingebouwd of door de gebruiker is gedefinieerd) wanneer deze automatisch wordt gedefinieerd, wordt een eigenschap genoemd "prototype" waarvan de waarde standaard is ingesteld als een object. Dit object zelf heeft een eigenschap genaamd "Constructeur" die standaard refereert naar de Constructor / functie .

Bijvoorbeeld wanneer we een functie definiëren

function UserDefinedFunction()
{
}

volgen gebeurt automatisch

UserDefinedFunction.prototype={constructor:UserDefinedFunction}

Deze eigenschap "prototype" is alleen aanwezig in de Functie type objecten  (en nooit binnen Niet-functionele type objecten).

Dit is zo omdat wanneer een nieuw object wordt gemaakt (met behulp van een nieuwe operator), neemt het alle eigenschappen en methoden over van het huidige prototype-object van de Constructorfunctie, dat wil zeggen een  interne referentie  wordt gemaakt in het nieuw gemaakte object dat verwijst naar het object waarnaar wordt verwezen door het huidige prototypeobject van de Constructorfunctie.

Deze "interne referentie" die is gemaakt in het object voor het verwijzen naar overgenomen eigenschappen staat bekend als de het prototype van het object (die verwijst naar het object waarnaar wordt verwezen door Constructor's "prototype" eigendom maar is anders). Voor elk object (functie of niet-functie) kan dit worden opgehaald met Object.getPrototypeOf () methode. Met behulp van deze methode kan men de prototypeketen van een object traceren.

Ook, elk object dat is gemaakt (Functietype of Niet-functietype) heeft een "Constructeur" eigenschap die is overgenomen van het object waarnaar wordt verwezen door de prototype-eigenschap van de functie Constructor. Standaard dit "Constructeur" eigenschap verwijst naar de Constructorfunctie dat creëerde het (als het Constructorfuncties standaard "prototype" is niet gewijzigd).

Voor iedereen Functie type objecten de constructorfunctie is altijd functie Functie () {}

Voor Niet-functionele type objecten (bijvoorbeeld het JavaScript Built-in-Math-object) de constructorfunctie is de functie die deze heeft gemaakt. Voor Wiskunde object is het functie Object () {}.

Al het hierboven toegelichte concept kan een beetje ontmoedigend zijn om te begrijpen zonder enige ondersteunende code. Volg de volgende code regel voor regel om het concept te begrijpen. Probeer het uit te voeren om een ​​beter begrip te krijgen.

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"

De prototypeketen van elk object volgt uiteindelijk Object.prototype (dat zelf geen prototypeobject heeft). De volgende code kan worden gebruikt voor het traceren van de prototypeketen van een object

var o=Starting object;

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

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

De prototypeketting voor verschillende objecten werkt als volgt.

  • Elk Functie-object (inclusief ingebouwd Functie-object) -> Function.prototype -> Object.prototype -> null
  • Eenvoudige objecten (gemaakt door nieuw object () of {} inclusief ingebouwd Math-object) -> Object.prototype -> null
  • Object gemaakt met nieuw of Object.create -> Een of meer prototypeketens -> Object.prototype -> null

Gebruik het volgende om een ​​object zonder prototype te maken:

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

Men zou kunnen denken dat het instellen van de prototype-eigenschap van de Constructor op null een object met een nul-prototype zal creëren. In dergelijke gevallen wordt het prototype van het nieuwe object echter ingesteld op Object.prototype en wordt de constructor ingesteld op functie Object. Dit wordt aangetoond door de volgende 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

In de samenvatting van dit artikel volgen

  • Er zijn twee soorten objecten Functietypen en Niet-functietypen
  • Enkel en alleen Functie type objecten kan een nieuw object maken met behulp van de operator nieuw. De aldus gecreëerde objecten zijn Niet-functietype voorwerpen. De Niet-functionele type objecten kan niet verder een object maken met behulp van operator nieuw.

  • Alle Functie type objecten standaard hebben een "prototype" eigendom. Deze "prototype" eigenschap verwijst naar een object met een "Constructeur" eigenschap die standaard verwijst naar de Functie type object zelf.

  • Alle objecten (Functietype en Niet-functietype) hebben een "constructor" eigenschap die standaard verwijst naar de Functie type object/bouwer dat heeft het gemaakt.

  • Elk object dat intern wordt aangemaakt, verwijst naar het object waarnaar wordt verwezen "prototype" eigendom van de Constructor die het heeft gemaakt. Dit object staat bekend als het gemaakte het prototype van het object (wat verschilt van het "prototype" -eigenschap van het Functietype waarnaar het verwijst). Op deze manier kan het gemaakte object rechtstreeks toegang krijgen tot de methoden en eigenschappen die zijn gedefinieerd in het object waarnaar wordt verwezen door de "prototype" -eigenschap van de Constructor (op het moment van het maken van het object).

  • Een het prototype van het object (en vandaar de overgenomen eigendomsnamen) kunnen worden opgehaald met behulp van de Object.getPrototypeOf ()   methode. In feite deze methode kan worden gebruikt voor het navigeren door de hele prototypeketen van het object.

  • De prototypeketen van elk object volgt uiteindelijk Object.prototype (tenzij het object is gemaakt met Object.create (null), in welk geval het object geen prototype heeft).

  • typeof (nieuw Array ()) === 'object' is door het ontwerp van de taal en niet een vergissing zoals gewezen Douglas Crockford 

  • Het instellen van de prototype-eigenschap van de Constructor op null (of ongedefinieerd, getal, waar, onwaar, string) zal geen object met een nul-prototype creëren. In dergelijke gevallen wordt het prototype van het nieuw gemaakte object ingesteld op Object.prototype en wordt de constructor ingesteld op functie Object.

Ik hoop dat dit helpt.


23
2017-07-03 21:44



Het concept van prototypal overerving is een van de meest gecompliceerde voor veel ontwikkelaars. Laten we proberen de oorzaak van het probleem te begrijpen prototypal inheritance beter. Laten we beginnen met een plain functie.

enter image description here

Als we een gebruiken new operator op de Tree function, we noemen het als een constructor functie.

enter image description here

elk JavaScript functie heeft een prototype. Wanneer u zich aanmeldt Tree.prototype, Jij krijgt...

enter image description here

Als je naar het bovenstaande kijkt console.log() output, zou je een constructeur-eigenschap kunnen zien Tree.prototype en een __proto__ eigendom ook. De __proto__ vertegenwoordigt de prototype dat dit function is gebaseerd op, en omdat dit gewoon een unicum is JavaScript function zonder inheritance ingesteld nog, het verwijst naar de Object prototype wat net iets is ingebouwd in JavaScript ...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

Dit heeft dingen als .toString, .toValue, .hasOwnProperty enz...

__proto__ die werd gebracht mijn mozilla is verouderd en wordt vervangen door Object.getPrototypeOf methode om de object's prototype.

enter image description here

Object.getPrototypeOf(Tree.prototype); // Object {} 

Laten we een methode toevoegen aan onze Tree  prototype.

enter image description here

We hebben de Root en voegde een toe functionvertakken.

enter image description here

Dat betekent wanneer u een maakt instance van Tree, je kunt het noemen branch methode.

enter image description here

We kunnen ook toevoegen primitives of objects naar onze Prototype.

enter image description here

Laten we er een toevoegen child-tree naar onze Tree.

enter image description here

Hier de Child erft zijn prototype van Tree, wat we hier doen is gebruiken Object.create() methode om een ​​nieuw object te maken op basis van wat u passeert, hier is het Tree.prototype. In dit geval is wat we doen het instellen van het prototype van Kind op een nieuw object dat er hetzelfde uitziet als het Tree prototype. Vervolgens stellen we de Child's constructor to Child, als we dat niet doen, zou het wijzen Tree().

enter image description here

Child heeft nu zijn eigen prototype, het is __proto__ wijst naar Tree en Tree's prototype wijst naar basis Object.

Child  
|
 \
  \
   Tree.prototype
   - branch
   |
   |
    \
     \
      Object.prototype
      -toString
      -valueOf
      -etc., etc.

Nu maak je een instance van Child en bel branch die oorspronkelijk beschikbaar is in Tree. We hebben ons niet echt gedefinieerd branch op de Child prototype. MAAR, in de Root prototype welk kind erft van.

enter image description here

In JS is alles geen object, alles kan als een object fungeren.

Javascript heeft primitieven zoals strings, number, booleans, undefined, null. Zij zijn niet object(i.e reference types), maar kan zeker als een object. Laten we hier een voorbeeld bekijken.

enter image description here

In de eerste regel van deze aanbieding, primitive reekswaarde is toegewezen aan naam. De tweede regel behandeld naam als een object en oproepen charAt(0) met behulp van puntnotatie.

Dit gebeurt er achter de schermen: // wat de JavaScript motor doet

enter image description here

De String object bestaat slechts voor één verklaring voordat deze wordt vernietigd (een proces genaamd autoboxing). Laten we opnieuw teruggaan naar onze prototypal  inheritance.

  • Javascript ondersteunt overerving via delegation gebaseerd op prototypes.
  • Elk Function heeft een prototype eigenschap, die naar een andere verwijst voorwerp.
  • properties/functions zijn gekeken vanaf de object zichzelf of via prototype ketting als het niet bestaat

EEN prototype in JS is een object dat yields jij naar de ouder van een ander object. [ie .. delegatie]  Delegation betekent dat als u iets niet kunt doen, u iemand anders vertelt het voor u te doen.

enter image description here

https://jsfiddle.net/say0tzpL/1/

Als je de bovenstaande viool opzoekt, heeft de hond toegang tot toString methode, maar deze is niet beschikbaar, maar is beschikbaar via de prototypeketen die delegeert naar Object.prototype

enter image description here

Als je naar de onderstaande kijkt, proberen we toegang te krijgen tot de call methode die beschikbaar is in elke function.

enter image description here

https://jsfiddle.net/rknffckc/

Als je de bovenstaande viool opzoekt, Profile Functie heeft toegang tot call methode, maar deze is niet beschikbaar, maar is beschikbaar via de prototypeketen die delegeert naar Function.prototype

enter image description here

Notitie:  prototype is een eigenschap van de functieconstructor, terwijl __proto__ is een eigenschap van de objecten die zijn geconstrueerd van de functieconstructor. Elke functie wordt geleverd met een prototype eigenschap waarvan de waarde leeg is object. Wanneer we een instantie van de functie maken, krijgen we een interne eigenschap [[Prototype]] of __proto__ waarvan de referentie het prototype van de functie is constructor.

enter image description here

Het bovenstaande diagram ziet er wat ingewikkeld uit, maar brengt het hele plaatje naar boven hoe prototype chaining werken. Laten we dit langzaam doorlopen:

Er zijn twee gevallen b1 en b2, waarvan de constructor is Bar en ouder is Foo en heeft twee methoden uit de prototypeketen identify en speak via Bar en Foo

enter image description here

https://jsfiddle.net/kbp7jr7n/

Als je de bovenstaande code opzoekt, hebben we dat gedaan Fooconstructor die de methode heeft identify() en Bar constructor die heeft speak methode. We creëren er twee Bar aanleg b1 en b2 waarvan het bovenliggende type is Foo. Nu tijdens het bellen speak methode van Bar, we zijn in staat om te identificeren met wie de spreker is prototype keten.

enter image description here

Bar heeft nu alle methoden van Foo die zijn gedefinieerd in zijn prototype. Laten we verder graven in het begrijpen van de Object.prototype en Function.prototype en hoe ze gerelateerd zijn. Als je de constructor opzoekt van Foo, Bar en Object zijn Function constructor.

enter image description here

De prototype van Bar is Foo, prototype van Foo is Object en als je goed kijkt naar de prototype van Foo is gerelateerd aan Object.prototype.

enter image description here

Voordat we dit afsluiten, laten we hier een klein stukje code omzetten vat alles hierboven samen. Wij gebruiken instanceof operator hier om te controleren of een object heeft in zijn prototype keten de prototype eigendom van een constructor welke hieronder het hele grote diagram samenvat.

enter image description here

Ik hoop dat deze add enige informatie is, ik weet dat dit nogal groot kan zijn om te begrijpen ... in simpele woorden zijn het zijn gewoon objecten gekoppeld aan objecten !!!! 


19
2018-02-21 12:37