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