Jest to bardzo prosty prototypowy model obiektowy, który podczas objaśnienia byłby traktowany jako próbka, bez komentarza:
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
console.log(this.name);
}
var person = new Person("George");
Jest kilka kluczowych punktów, które musimy wziąć pod uwagę przed omówieniem koncepcji prototypu.
1- Jak faktycznie działają funkcje JavaScript:
Aby zrobić pierwszy krok, musimy dowiedzieć się, jak faktycznie działają funkcje JavaScript, jako klasa taka jak funkcja wykorzystująca thissłowo kluczowe lub po prostu jako zwykła funkcja z argumentami, co robi i co zwraca.
Powiedzmy, że chcemy stworzyć Personmodel obiektowy. ale w tym kroku będę próbował zrobić dokładnie to samo bez użycia słowa kluczowego prototypeinew .
Więc na tym etapie functions, objectsa thissłowa kluczowego, to wszystko, co mamy.
Pierwszym pytaniem byłoby, w jaki sposób thissłowo kluczowe może być przydatne bez użycia newsłowa kluczowego .
Aby odpowiedzieć, powiedzmy, że mamy pusty obiekt i dwie funkcje, takie jak:
var person = {};
function Person(name){ this.name = name; }
function getName(){
console.log(this.name);
}
a teraz bez użycia newsłowa kluczowego, w jaki sposób moglibyśmy korzystać z tych funkcji. JavaScript ma więc 3 różne sposoby:
za. pierwszym sposobem jest wywołanie funkcji jako zwykłej funkcji:
Person("George");
getName();//would print the "George" in the console
w tym przypadku byłby to bieżący obiekt kontekstu, którym zwykle jest windowobiekt globalny w przeglądarce lub GLOBALw Node.js. Oznacza to, że mielibyśmy, window.name w przeglądarce lub GLOBAL.name w Node.js, z „George” jako jego wartością.
b. Możemy dołączyć je do obiektu jako jego właściwości
- Najłatwiej to zrobić, modyfikując pusteperson obiekt, na przykład:
person.Person = Person;
person.getName = getName;
w ten sposób możemy je nazwać:
person.Person("George");
person.getName();// -->"George"
a teraz personobiekt jest jak:
Object {Person: function, getName: function, name: "George"}
- Innym sposobem dołączenia właściwości do obiektu jest użycie prototypetego obiektu, który można znaleźć w dowolnym obiekcie JavaScript o nazwie __proto__, i próbowałem wyjaśnić to trochę w części podsumowującej. Możemy więc uzyskać podobny wynik, wykonując:
person.__proto__.Person = Person;
person.__proto__.getName = getName;
Ale w ten sposób faktycznie modyfikujemy Object.prototype, ponieważ za każdym razem, gdy tworzymy obiekt JavaScript za pomocą literals ( { ... }), jest on tworzony na podstawie Object.prototype, co oznacza, że zostaje on dołączony do nowo utworzonego obiektu jako atrybut o nazwie__proto__ , więc jeśli go zmienimy , podobnie jak w przypadku naszego poprzedniego fragmentu kodu, wszystkie obiekty JavaScript zostałyby zmienione, co nie jest dobrą praktyką. Więc jaka może być teraz lepsza praktyka:
person.__proto__ = {
Person: Person,
getName: getName
};
a teraz inne przedmioty są spokojne, ale nadal nie wydaje się to dobrą praktyką. Mamy więc jeszcze jedno rozwiązanie, ale aby skorzystać z tego rozwiązania, powinniśmy wrócić do tego wiersza kodu, w którym personutworzono obiekt (var person = {}; ), a następnie zmienić go w następujący sposób:
var propertiesObject = {
Person: Person,
getName: getName
};
var person = Object.create(propertiesObject);
tworzy nowy JavaScript Objecti dołącza go propertiesObjectdo pliku__proto__ atrybutu. Aby upewnić się, że możesz:
console.log(person.__proto__===propertiesObject); //true
Problem w tym, że masz dostęp do wszystkich właściwości zdefiniowanych __proto__na pierwszym poziomieperson obiektu (więcej szczegółów znajdziesz w części podsumowującej).
jak widzisz, używając dowolnego z tych dwóch sposobów this wskazywałoby dokładnie na personobiekt.
do. JavaScript ma inny sposób na zapewnienie funkcji this, która polega na wywołaniu lub zastosowaniu do wywołania funkcji.
Metoda apply () wywołuje funkcję o podanej wartości i argumentach podanych jako tablica (lub obiekt podobny do tablicy).
i
Metoda call () wywołuje funkcję o podanej wartości i argumentach podanych indywidualnie.
w ten sposób, który jest moim ulubionym, możemy łatwo wywoływać nasze funkcje, takie jak:
Person.call(person, "George");
lub
//apply is more useful when params count is not fixed
Person.apply(person, ["George"]);
getName.call(person);
getName.apply(person);
te 3 metody są ważnymi początkowymi krokami do zrozumienia funkcjonalności .prototypu.
2- Jak działa new słowo kluczowe?
to jest drugi krok do zrozumienia .prototypefunkcjonalności. oto, czego używam do symulacji procesu:
function Person(name){ this.name = name; }
my_person_prototype = { getName: function(){ console.log(this.name); } };
w tej części postaram się wykonać wszystkie kroki, które wykonuje JavaScript, bez użycia newsłowa kluczowego i prototype, gdy używasz newsłowa kluczowego. więc kiedy to robimy new Person("George"), Personfunkcja służy jako konstruktor. Oto, co robi JavaScript, jeden po drugim:
za. po pierwsze tworzy pusty obiekt, w zasadzie pusty skrót, taki jak:
var newObject = {};
b. następnym krokiem JavaScript jest dołączenie wszystkich prototypowych obiektów do nowo utworzonego obiektu
mamy my_person_prototypetutaj podobny do obiektu prototypowego.
for(var key in my_person_prototype){
newObject[key] = my_person_prototype[key];
}
To nie jest sposób, w jaki JavaScript faktycznie dołącza właściwości zdefiniowane w prototypie. Rzeczywisty sposób związany jest z koncepcją łańcucha prototypów.
za. & b. Zamiast tych dwóch kroków możesz uzyskać dokładnie taki sam wynik, wykonując:
var newObject = Object.create(my_person_prototype);
//here you can check out the __proto__ attribute
console.log(newObject.__proto__ === my_person_prototype); //true
//and also check if you have access to your desired properties
console.log(typeof newObject.getName);//"function"
teraz możemy wywołać getNamefunkcję w naszym my_person_prototype:
newObject.getName();
do. następnie przekazuje ten obiekt do konstruktora,
możemy to zrobić za pomocą naszej próbki, takiej jak:
Person.call(newObject, "George");
lub
Person.apply(newObject, ["George"]);
wtedy konstruktor może zrobić, co chce, ponieważ to wewnątrz tego konstruktora jest obiekt, który został właśnie utworzony.
teraz wynik końcowy przed symulacją innych kroków: Object {name: "George"}
Podsumowanie:
Zasadniczo, gdy używasz nowego słowa kluczowego w funkcji, wywołujesz tę funkcję, a ta funkcja służy jako konstruktor, więc mówiąc:
new FunctionName()
JavaScript wewnętrznie tworzy obiekt, pusty skrót, a następnie przekazuje ten obiekt do konstruktora, a następnie konstruktor może zrobić co chce, ponieważ to wewnątrz tego konstruktora jest właśnie utworzonym obiektem, a następnie daje ten obiekt oczywiście jeśli nie użyłeś instrukcji return w swojej funkcji lub jeśli umieściłeś return undefined;na końcu treści funkcji.
Kiedy JavaScript zaczyna szukać właściwości na obiekcie, pierwszą rzeczą, którą robi, jest wyszukiwanie na tym obiekcie. A potem jest tajna właściwość, [[prototype]]którą zwykle mamy, __proto__a ta właściwość właśnie patrzy na JavaScript. A kiedy przegląda __proto__, o ile jest to kolejny obiekt JavaScript, ma swój własny __proto__atrybut, idzie w górę i w górę, aż dojdzie do punktu, w którym następny __proto__jest pusty. Punkt jest jedynym obiektem w JavaScript, którego __proto__atrybut ma wartość null, to Object.prototypeobiekt:
console.log(Object.prototype.__proto__===null);//true
i tak działa dziedziczenie w JavaScript.

Innymi słowy, gdy masz właściwość prototypową funkcji i wywołujesz nową funkcję, po zakończeniu JavaScript w poszukiwaniu tego nowo utworzonego obiektu pod kątem właściwości, przejdzie on do funkcji .prototypei możliwe jest, że ten obiekt ma swoją własny wewnętrzny prototyp. i tak dalej.