Перша різниця може бути зведена як: 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!"
.
Щодо плюсів і мінусів кожного методу, ви можете розглядати прототипування як "більш ефективний" спосіб виконання дій, оскільки він зберігає посилання на кожен примірник, а не копіює всю властивість у кожному об'єкті. З іншого боку, це приклад жорсткого зчеплення який є великим «ні-ні», поки ви дійсно не зможете виправдати причину. 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
має більше сенсу брати перевагу, оскільки мова йде про новий екземпляр, який створюється в цей момент.