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

Źródło: http://javascript.crockford.com/prototypal.html


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.

6

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

5

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
6

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.

5

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.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow