In JavaScript kunnen functies eigenschappen hebben. Alle functies hebben een speciale eigenschap genaamd prototype
.
function doSomething() {}
console.log(doSomething.prototype);
// Functies in JavaScript hebben altijd een standaard prototype eigenschap
// Uitzondering: arrow functies hebben geen standaard prototype eigenschap
const doSomethingFromArrowFunction = () => {};
console.log(doSomethingFromArrowFunction.prototype);
doSomething()
heeft een standaard prototype
eigenschap. Na het uitvoeren van bovenstaande code, zal de console een object tonen dat er ongeveer zo uitziet:
{ constructor: ƒ doSomething(), [[Prototype]]: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } }
Let op: De Chrome console gebruikt [[Prototype]]
om de prototype van het object aan te duiden, volgens de specificatie; Firefox gebruikt .prototype
. Voor de consistentie gebruiken we [[Prototype]]
.
We kunnen eigenschappen toevoegen aan de prototype van doSomething()
:
function doSomething() {}
doSomething.prototype.foo = "bar";
console.log(doSomething.prototype);
Resultaat:
{ foo: "bar", constructor: ƒ doSomething(), [[Prototype]]: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } }
Gebruik de new
operator om een instantie van doSomething()
te creëren op basis van deze prototype. Het aanroepen van een functie met de new
operator retourneert een object dat een instantie is van de functie. Eigenschappen kunnen vervolgens aan dit object worden toegevoegd.
function doSomething() {}
doSomething.prototype.foo = "bar"; // voeg eigenschap toe aan de prototype
const doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value"; // voeg eigenschap toe aan het object
console.log(doSomeInstancing);
Resultaat:
{ prop: "some value", [[Prototype]]: { foo: "bar", constructor: ƒ doSomething(), [[Prototype]]: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } } }
De [[Prototype]]
van doSomeInstancing
is doSomething.prototype
. Bij het opvragen van een eigenschap van doSomeInstancing
, controleert de runtime eerst of doSomeInstancing
die eigenschap heeft.
Zo niet, dan zoekt de runtime naar de eigenschap in doSomeInstancing.[[Prototype]]
(dus doSomething.prototype
). Als doSomeInstancing.[[Prototype]]
de gezochte eigenschap heeft, dan wordt die eigenschap gebruikt.
Zo niet, dan wordt doSomeInstancing.[[Prototype]].[[Prototype]]
gecontroleerd. Standaard is de [[Prototype]]
van de prototype
eigenschap van elke functie Object.prototype
. Dus doSomeInstancing.[[Prototype]].[[Prototype]]
(dus doSomething.prototype.[[Prototype]]
of Object.prototype
) wordt doorzocht. Dit proces heet prototype chain.
Als de eigenschap niet wordt gevonden in doSomeInstancing.[[Prototype]].[[Prototype]]
, dan wordt doSomeInstancing.[[Prototype]].[[Prototype]].[[Prototype]]
doorzocht. Echter, doSomeInstancing.[[Prototype]].[[Prototype]].[[Prototype]]
bestaat niet, omdat Object.prototype.[[Prototype]]
null
is. Nadat de gehele prototype chain is doorzocht, concludeert de runtime dat de eigenschap niet bestaat en is de waarde van de eigenschap undefined
.
function doSomething() {}
doSomething.prototype.foo = "bar";
const doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value";
console.log("doSomeInstancing.prop: ", doSomeInstancing.prop);
console.log("doSomeInstancing.foo: ", doSomeInstancing.foo);
console.log("doSomething.prop: ", doSomething.prop);
console.log("doSomething.foo: ", doSomething.foo);
console.log("doSomething.prototype.prop:", doSomething.prototype.prop);
console.log("doSomething.prototype.foo: ", doSomething.prototype.foo);
Resultaat:
doSomeInstancing.prop: some value
doSomeInstancing.foo: bar
doSomething.prop: undefined
doSomething.foo: undefined
doSomething.prototype.prop: undefined
doSomething.prototype.foo: bar