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

Källa: http://javascript.crockford.com/prototypal.html


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.

6

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

5

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
6

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.

5

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.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow