Первое различие можно суммировать как: 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
имеет больше смысла иметь приоритет, потому что все дело в том, что новый экземпляр создается в этот момент.