Sök…
Standardfunktionsprototyp
Börja med att definiera en Foo
funktion som vi ska använda som konstruktör.
function Foo (){}
Genom att redigera Foo.prototype
kan vi definiera egenskaper och metoder som kommer att delas av alla förekomster av Foo
.
Foo.prototype.bar = function() {
return 'I am bar';
};
Vi kan sedan skapa en instans med det new
nyckelordet och ringa metoden.
var foo = new Foo();
console.log(foo.bar()); // logs `I am bar`
Skillnad mellan Object.key och Object.prototype.key
Till skillnad från i språk som Python ärvs inte statiska egenskaper hos konstruktörsfunktionen till fall. Instanser ärver bara från sin prototyp, som ärver från föräldertypens prototyp. Statiska egenskaper ärvs aldrig.
function Foo() {};
Foo.style = 'bold';
var foo = new Foo();
console.log(Foo.style); // 'bold'
console.log(foo.style); // undefined
Foo.prototype.style = 'italic';
console.log(Foo.style); // 'bold'
console.log(foo.style); // 'italic'
Nytt objekt från prototyp
I JavaScript kan alla objekt vara prototypen till en annan. När ett objekt skapas som en prototyp av en annan kommer det att ärva alla dess överordnade egenskaper.
var proto = { foo: "foo", bar: () => this.foo };
var obj = Object.create(proto);
console.log(obj.foo);
console.log(obj.bar());
Konsolutgång:
> "foo"
> "foo"
OBS Object.create
är tillgängligt från ECMAScript 5, men här är en polyfyll om du behöver support för ECMAScript 3
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
Object.create ()
Metoden Object.create () skapar ett nytt objekt med det angivna prototypobjektet och egenskaperna.
Syntax: Object.create(proto[, propertiesObject])
Parametrar :
- proto (Objektet som ska vara prototypen för det nyligen skapade objektet.)
- egenskaperObjekt (Valfritt. Om det är specificerat och inte odefinierat, anger ett objekt vars uppräknbara egna egenskaper (det vill säga de egenskaper som definieras på sig själv och inte uppräknbara egenskaper längs sin prototypkedja) egenskapsbeskrivningar som ska läggas till det nyskapade objektet, med motsvarande Egenskapsnamn. Dessa egenskaper motsvarar det andra argumentet från Object.defineProperties ().)
Returvärde
Ett nytt objekt med det angivna prototypobjektet och egenskaperna.
undantag
Ett TypeError- undantag om proto-parametern inte är noll eller ett objekt.
Prototyp arv
Anta att vi har ett vanligt objekt som heter prototype
:
var prototype = { foo: 'foo', bar: function () { return this.foo; } };
Nu vill vi ha ett annat objekt som heter obj
som ärver från prototype
, vilket är detsamma som att säga att prototype
är prototypen för obj
var obj = Object.create(prototype);
Nu kommer alla egenskaper och metoder från prototype
att vara tillgängliga för obj
console.log(obj.foo);
console.log(obj.bar());
Konsolutgång
"foo"
"foo"
Prototyparv görs internt genom objektreferenser och objekt är fullständigt muterbara. Detta innebär att alla ändringar du gör på en prototyp kommer omedelbart att påverka alla andra objekt som prototypen är prototyp av.
prototype.foo = "bar";
console.log(obj.foo);
Konsolutgång
"bar"
Object.prototype
är prototypen för varje objekt, så det rekommenderas starkt att du inte orkar med det, speciellt om du använder något tredje parts bibliotek, men vi kan leka med det lite.
Object.prototype.breakingLibraries = 'foo';
console.log(obj.breakingLibraries);
console.log(prototype.breakingLibraries);
Konsolutgång
"foo"
"foo"
Roligt faktum Jag har använt webbläsarkonsolen för att göra dessa exempel och har brutit den här sidan genom att lägga till den breakingLibraries
egenskapen.
Pseudoklassisk arv
Det är en emulering av klassisk arv som använder prototypiska arv som visar hur kraftfulla prototyper är. Det gjordes för att göra språket mer attraktivt för programmerare som kommer från andra språk.
VIKTIGT ANMÄRKNING : Eftersom ES6 är det inte vettigt att använda pseudokalskisk arv eftersom språket simulerar konventionella klasser . Om du inte använder ES6 bör du göra det . Om du fortfarande vill använda det klassiska arvsmönstret och du befinner dig i en ECMAScript 5 eller lägre miljö, är pseudoklassisk din bästa insats.
En "klass" är bara en funktion som kallas för den new
operand och den används som en konstruktör.
function Foo(id, name) {
this.id = id;
this.name = name;
}
var foo = new Foo(1, 'foo');
console.log(foo.id);
Konsolutgång
1
foo är ett exempel på Foo. JavaScript-kodningskonventionen säger att om en funktion börjar med en stor bokstav kan den kallas som en konstruktör (med den new
operand).
För att lägga till egenskaper eller metoder till "klassen" måste du lägga till dem till sin prototyp, som kan hittas i prototype
för konstruktören.
Foo.prototype.bar = 'bar';
console.log(foo.bar);
Konsolutgång
bar
Faktum är att vad Foo gör som en "konstruktör" bara skapar objekt med Foo.prototype
som sin prototyp.
Du hittar en referens till dess konstruktör på varje objekt
console.log(foo.constructor);
funktion Foo (id, namn) {...
console.log({ }.constructor);
function Object () {[native code]}
Och kontrollera också om ett objekt är ett exempel på en viss klass hos operatörens instanceof
console.log(foo instanceof Foo);
Sann
console.log(foo instaceof Object);
Sann
Ställa in ett objekts prototyp
Med ES5 + Object.create
funktionen Object.create
användas för att skapa ett objekt med något annat objekt eftersom det är prototyp.
const anyObj = {
hello() {
console.log(`this.foo is ${this.foo}`);
},
};
let objWithProto = Object.create(anyObj);
objWithProto.foo = 'bar';
objWithProto.hello(); // "this.foo is bar"
För att uttryckligen skapa ett objekt utan en prototyp använder du null
som prototyp. Detta innebär att objektet inte kommer att ärva från Object.prototype
heller och är användbart för objekt som används för att kontrollera ordböcker, t.ex.
let objInheritingObject = {};
let objInheritingNull = Object.create(null);
'toString' in objInheritingObject; // true
'toString' in objInheritingNull ; // false
Från ES6 kan prototypen för ett befintligt objekt ändras med exempelvis Object.setPrototypeOf
let obj = Object.create({foo: 'foo'});
obj = Object.setPrototypeOf(obj, {bar: 'bar'});
obj.foo; // undefined
obj.bar; // "bar"
Detta kan göras nästan var som helst, inklusive på this
objekt eller i en konstruktör.
Obs! Den här processen går mycket långsamt i nuvarande webbläsare och bör användas sparsamt, försök att skapa objektet med önskad prototyp istället.
Innan ES5, det enda sättet att skapa ett objekt med en manuellt definierad prototyp var att konstruera det med new
, till exempel
var proto = {fizz: 'buzz'};
function ConstructMyObj() {}
ConstructMyObj.prototype = proto;
var objWithProto = new ConstructMyObj();
objWithProto.fizz; // "buzz"
Detta beteende är tillräckligt nära Object.create
att det är möjligt att skriva en polyfyll.