Первое различие можно суммировать как: thisотносится к экземпляру класса. prototypeотносится к определению .
Допустим, у нас есть следующий класс:
var Flight = function ( number ) { this.number = number; };
Так что здесь мы прикрепляемся this.numberк каждому экземпляру класса, и это имеет смысл, потому что у каждого Flightдолжен быть свой номер рейса.
var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );
Напротив, prototypeопределяет единственное свойство, к которому могут обращаться все экземпляры.
Теперь, если мы хотим получить номер рейса, мы можем просто написать следующий фрагмент, и все наши экземпляры получат ссылку на этот недавно созданный прототип объекта.
Flight.prototype.getNumber = function () { return this.number; };
Второе отличие заключается в том, как JavaScript ищет свойство объекта. Когда вы ищете Object.whatever, JavaScript проходит вплоть до основного объекта Object (объекта, от которого все остальное унаследовано), и как только он находит совпадение, он возвращает или вызывает его.
Но это происходит только для прототипов. Так что, если вы находитесь где-то на более высоких уровнях this.whatever, JavaScript не будет рассматривать это как совпадение и продолжит поиск.
Посмотрим, как это происходит на самом деле.
Сначала обратите внимание, что [почти] все объекты в JavaScript. Попробуй это:
typeof null
Теперь давайте посмотрим, что внутри Object(обратите внимание на верхний регистр Oи .в конце). В инструментах разработчика Google Chrome при вводе .вы получите список доступных свойств внутри этого конкретного объекта.
Object.
Теперь сделайте то же самое для Function:
Function.
Вы можете заметить nameметод. Просто иди и запусти и посмотрим, что получится:
Object.name
Function.name
Теперь давайте создадим функцию:
var myFunc = function () {};
И давайте посмотрим, есть ли у нас nameздесь метод:
myFunc.name
Вы должны получить пустую строку, но это нормально. Вы не должны получить ошибку или исключение.
Теперь давайте добавим что-нибудь к этому богоподобному Objectи посмотрим, получим ли мы это и в других местах?
Object.prototype.test = "Okay!";
И вот вы идете:
Object.prototype.test
Function.prototype.test
myFunc.prototype.test
Во всех случаях вы должны увидеть "Okay!".
Что касается плюсов и минусов каждого метода, вы можете рассматривать прототипирование как «более эффективный» способ выполнения задач, поскольку он сохраняет ссылку на каждый экземпляр, а не копирует все свойство в каждом объекте. С другой стороны, это пример Tightly Coupling, который является большим нет-нет, пока вы действительно не сможете обосновать причину. thisэто довольно сложно, так как это имеет отношение к контексту. Вы можете найти много хороших ресурсов бесплатно в Интернете.
Тем не менее, оба способа являются лишь языковыми инструментами, и это действительно зависит от вас и от проблемы, которую вы пытаетесь решить, чтобы выбрать то, что подходит лучше.
Если вам нужно, чтобы свойство имело отношение к каждому экземпляру класса, используйте this. Если вам нужно иметь свойство, чтобы оно функционировало одинаково на каждом экземпляре, используйте prototype.
Обновить
Что касается ваших образцов фрагментов, то первый пример является примером Singleton , поэтому имеет смысл использовать его thisв теле объекта. Вы также можете улучшить свой пример, сделав его модульным, как этот (и вам не обязательно всегда использовать его this).
/* Assuming it will run in a web browser */
(function (window) {
window.myApp = {
...
}
})( window );
/* And in other pages ... */
(function (myApp) {
myApp.Module = {
...
}
})( myApp );
/* And if you prefer Encapsulation */
(function (myApp) {
myApp.Module = {
"foo": "Foo",
"bar": function ( string ) {
return string;
},
return {
"foor": foo,
"bar": bar
}
}
})( myApp );
Ваш второй фрагмент не имеет особого смысла, потому что сначала вы используете, thisа потом пытаетесь его взломать prototype, что не работает, потому что thisимеет приоритет над prototype. Я не уверен, чего вы ожидали от этого фрагмента кода и как он работал, но я настоятельно рекомендую вам его реорганизовать.
Обновить
Чтобы уточнить thisприоритет, prototypeя могу показать вам пример и рассказать, как это можно объяснить, но у меня нет внешних ресурсов для его поддержки.
Пример очень прост:
var myClass = function () { this.foo = "Foo"; };
myClass.prototype.foo = "nice try!";
myClass.prototype.bar = "Bar";
var obj = new myClass;
obj.foo; // Still contains "Foo" ...
obj.bar; // Contains "Bar" as expected
Объяснение, как мы знаем, thisимеет отношение к контексту. Так что он не появится, пока контекст не будет готов. Когда контекст готов? Когда новый экземпляр создается! Остальное угадай сейчас! Это означает, что хотя prototypeопределение существует, но thisимеет больше смысла иметь приоритет, потому что все дело в том, что новый экземпляр создается в этот момент.