Szukaj…
Prototyp funkcji standardowej
Zacznij od zdefiniowania funkcji Foo
, której użyjemy jako konstruktora.
function Foo (){}
Poprzez edycję Foo.prototype
możemy zdefiniować właściwości i metody, które będą wspólne dla wszystkich instancji Foo
.
Foo.prototype.bar = function() {
return 'I am bar';
};
Następnie możemy utworzyć instancję za pomocą new
słowa kluczowego i wywołać metodę.
var foo = new Foo();
console.log(foo.bar()); // logs `I am bar`
Różnica między Object.key i Object.prototype.key
W przeciwieństwie do języków takich jak Python, właściwości statyczne funkcji konstruktora nie są dziedziczone po instancjach. Instancje dziedziczą tylko po prototypie, który dziedziczy po prototypie typu nadrzędnego. Właściwości statyczne nigdy nie są dziedziczone.
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'
Nowy obiekt z prototypu
W JavaScript każdy obiekt może być prototypem innego. Kiedy obiekt jest tworzony jako prototyp innego, odziedziczy wszystkie właściwości swojego rodzica.
var proto = { foo: "foo", bar: () => this.foo };
var obj = Object.create(proto);
console.log(obj.foo);
console.log(obj.bar());
Dane wyjściowe konsoli:
> "foo"
> "foo"
UWAGA Object.create
jest dostępny w ECMAScript 5, ale tutaj jest polifill, jeśli potrzebujesz wsparcia dla ECMAScript 3
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
Object.create ()
Metoda Object.create () tworzy nowy obiekt z określonym obiektem prototypowym i właściwościami.
Składnia: Object.create(proto[, propertiesObject])
Parametry :
- proto (Obiekt, który powinien być prototypem nowo utworzonego obiektu).
- propertiesObject (Opcjonalnie. Jeśli jest określony i nie jest zdefiniowany, obiekt, którego wyliczalne właściwości własne (to znaczy właściwości zdefiniowane na sobie i właściwości niepoliczalne w łańcuchu prototypowym) określa deskryptory właściwości, które mają zostać dodane do nowo utworzonego obiektu, wraz z odpowiednim nazwy właściwości. Właściwości te odpowiadają drugiemu argumentowi Object.defineProperties ().)
Zwracana wartość
Nowy obiekt z określonym obiektem prototypowym i właściwościami.
Wyjątki
Wyjątek TypeError, jeśli parametr proto nie jest pusty lub jest obiektem.
Dziedziczenie prototypowe
Załóżmy, że mamy prosty obiekt o nazwie prototype
:
var prototype = { foo: 'foo', bar: function () { return this.foo; } };
Teraz chcemy innego obiektu o nazwie obj
który dziedziczy po prototype
, co jest równoznaczne z powiedzeniem, że prototype
jest prototypem obj
var obj = Object.create(prototype);
Teraz wszystkie właściwości i metody z prototype
będą dostępne dla obj
console.log(obj.foo);
console.log(obj.bar());
Wyjście konsoli
"foo"
"foo"
Dziedziczenie prototypowe odbywa się poprzez wewnętrzne odwołania do obiektów, a obiekty są całkowicie zmienne. Oznacza to, że każda zmiana dokonana w prototypie natychmiast wpłynie na każdy inny obiekt, którego prototyp jest prototypem.
prototype.foo = "bar";
console.log(obj.foo);
Wyjście konsoli
"bar"
Object.prototype
jest prototypem każdego obiektu, więc zdecydowanie zaleca się, aby z nim nie zadzierać, szczególnie jeśli korzystasz z biblioteki innej firmy, ale możemy się nią trochę pobawić.
Object.prototype.breakingLibraries = 'foo';
console.log(obj.breakingLibraries);
console.log(prototype.breakingLibraries);
Wyjście konsoli
"foo"
"foo"
Zabawne, że wykorzystałem konsolę przeglądarki, aby zrobić te przykłady, i zepsułem tę stronę, dodając właściwość breakingLibraries
.
Dziedziczenie pseudoklasyczne
Jest to emulacja klasycznego dziedziczenia z wykorzystaniem dziedziczenia prototypowego, która pokazuje, jak potężne są prototypy. Został stworzony, aby uczynić język bardziej atrakcyjnym dla programistów pochodzących z innych języków.
WAŻNA UWAGA : Od wersji ES6 nie ma sensu używać dziedziczenia pseudokalipsalnego, ponieważ język symuluje klasyczne klasy . Jeśli nie używasz ES6, powinieneś . Jeśli nadal chcesz używać klasycznego wzorca dziedziczenia i znajdujesz się w środowisku ECMAScript 5 lub niższym, najlepszym wyborem jest pseudoklasyczny.
„Klasa” to po prostu funkcja, która jest wywoływana z new
operandem i jest używana jako konstruktor.
function Foo(id, name) {
this.id = id;
this.name = name;
}
var foo = new Foo(1, 'foo');
console.log(foo.id);
Wyjście konsoli
1
foo jest instancją Foo. Konwencja kodowania JavaScript mówi, że jeśli funkcja zaczyna się od dużej litery, to można ją wywołać jako konstruktor (z new
operandem).
Aby dodać właściwości lub metody do „klasy”, musisz dodać je do prototypu, który można znaleźć we właściwości prototype
konstruktora.
Foo.prototype.bar = 'bar';
console.log(foo.bar);
Wyjście konsoli
bar
W rzeczywistości to, co robi Foo jako „konstruktor”, tworzy obiekty z Foo.prototype
jako prototypem.
Odwołanie do jego konstruktora można znaleźć na każdym obiekcie
console.log(foo.constructor);
funkcja Foo (identyfikator, nazwa) {...
console.log({ }.constructor);
function Object () {[kod macierzysty]}
Sprawdź także, czy obiekt jest instancją danej klasy za pomocą operatora instanceof
console.log(foo instanceof Foo);
prawdziwe
console.log(foo instaceof Object);
prawdziwe
Ustawianie prototypu obiektu
W ES5 + funkcja Object.create
może być używana do tworzenia obiektu z dowolnym innym obiektem, ponieważ jest to 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"
Aby jawnie utworzyć obiekt bez prototypu, użyj null
jako prototypu. Oznacza to, że obiekt nie odziedziczy po Object.prototype
i jest użyteczny dla obiektów używanych do sprawdzania słowników, np.
let objInheritingObject = {};
let objInheritingNull = Object.create(null);
'toString' in objInheritingObject; // true
'toString' in objInheritingNull ; // false
Od ES6 prototyp istniejącego obiektu można zmienić na przykład za pomocą Object.setPrototypeOf
let obj = Object.create({foo: 'foo'});
obj = Object.setPrototypeOf(obj, {bar: 'bar'});
obj.foo; // undefined
obj.bar; // "bar"
Można to zrobić prawie wszędzie, w tym na this
obiekcie lub w konstruktorze.
Uwaga: Ten proces jest bardzo powolny w obecnych przeglądarkach i powinien być używany oszczędnie, zamiast tego spróbuj utworzyć Obiekt z pożądanym prototypem.
Przed ES5 jedynym sposobem na stworzenie obiektu z ręcznie zdefiniowanym prototypem było zbudowanie go na przykład z new
var proto = {fizz: 'buzz'};
function ConstructMyObj() {}
ConstructMyObj.prototype = proto;
var objWithProto = new ConstructMyObj();
objWithProto.fizz; // "buzz"
To zachowanie jest wystarczająco zbliżone do Object.create
, że można napisać polifill.