Яка різниця між
var A = function () {
this.x = function () {
//do something
};
};
і
var A = function () { };
A.prototype.x = function () {
//do something
};
a1.x !== a2.x
:; про прототип:a1.x === a2.x
Яка різниця між
var A = function () {
this.x = function () {
//do something
};
};
і
var A = function () { };
A.prototype.x = function () {
//do something
};
a1.x !== a2.x
:; про прототип:a1.x === a2.x
Відповіді:
Приклади мають дуже різні результати.
Перш ніж переглянути розбіжності, слід зазначити наступне:
[[Prototype]]
власність екземпляра .myObj.method()
), то ця функція в методі посилається на об'єкт. Якщо це не встановлено викликом або використанням bind , воно за замовчуванням застосовується до глобального об'єкта (вікно в браузері) або в строгому режимі, залишається невизначеним.Отже, ось фрагменти, про які йдеться,:
var A = function () {
this.x = function () {
//do something
};
};
У цьому випадку змінній A
присвоюється значення, яке є посиланням на функцію. Коли ця функція викликається за A()
допомогою функції, ця функція не встановлюється викликом, тому вона за замовчуванням відповідає глобальному об'єкту, і вираз this.x
є ефективним window.x
. Результатом є те, що посилання на вираження функції праворуч призначено window.x
.
У випадку:
var A = function () { };
A.prototype.x = function () {
//do something
};
відбувається щось зовсім інше. У першому рядку змінній A
присвоюється посилання на функцію. У JavaScript всі об'єкти функцій за замовчуванням мають властивість прототипу , тому немає окремого коду для створення об’єкта A.prototype .
У другому рядку A.prototype.x присвоюється посилання на функцію. Це створить властивість x, якщо воно не існує, або призначить нове значення, якщо воно є. Отже, різниця з першим прикладом, в якому властивість x об'єкта бере участь у виразі.
Ще один приклад наведено нижче. Він схожий на перший (і, можливо, те, про що ви хотіли запитати):
var A = new function () {
this.x = function () {
//do something
};
};
У цьому прикладі new
оператор був доданий перед виразом функції, так що функція викликається конструктором. При виклику за new
допомогою функції цієї функції встановлюється посилання на новий об'єкт, приватна [[Prototype]]
власність якого встановлена для посилання на відкритий прототип конструктора . Тож у заяві про призначення x
буде створено властивість для цього нового об’єкта. Коли викликається конструктором, функція повертає цей об'єкт за замовчуванням, тому немає необхідності в окремому return this;
операторі.
Для того, щоб перевірити , що має й властивість:
console.log(A.x) // function () {
// //do something
// };
Це нечасте використання нового, оскільки єдиний спосіб посилання на конструктор - це через A.constructor . Це було б набагато частіше робити:
var A = function () {
this.x = function () {
//do something
};
};
var a = new A();
Інший спосіб досягнення подібного результату - це використання виразу функції, що викликається негайно:
var A = (function () {
this.x = function () {
//do something
};
}());
У цьому випадку A
призначається повернене значення виклику функції з правого боку. Знову ж таки, оскільки це не встановлено у виклику, воно посилатиметься на глобальний об’єкт та this.x
є ефективним window.x
. Оскільки функція нічого не повертає, A
матиме значення undefined
.
Ці відмінності між двома підходами також виявляються, якщо ви серіалізуєте та десертуєте свої об'єкти Javascript до / з JSON. Методи, визначені в прототипі об'єкта, не серіалізуються під час серіалізації об'єкта, що може бути зручно, коли, наприклад, ви хочете серіалізувати лише частини даних об'єкта, але це не методи:
var A = function () {
this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance));
// {"objectsOwnProperties":"are serialized"}
Пов’язані запитання :
Сторінка: Можливо, між двома підходами не буде суттєвої економії пам’яті, однак використання прототипу для обміну методами та властивостями, швидше за все, буде використовувати менше пам'яті, ніж кожен екземпляр, який має власну копію.
JavaScript не є мовою низького рівня. Можливо, не дуже корисно думати про прототипування чи інші шаблони успадкування як спосіб явно змінити спосіб розподілу пам'яті.
null
), але це дуже відрізняється від prototype
властивості - яка функціонує та для якої встановлюється прототип усіх екземплярів, коли вони побудовані new
. Не можу повірити , що це на самому справі отримав 87 upvotes :-(
"The language is functional"
Ви впевнені, що це те, що функціонально означає?
A
функцію, а інша половина - про незрозумілі та неортодоксальні способи зробити щось прямолінійне.
Як говорили інші, у першій версії використання "цього" призводить до того, що кожен екземпляр класу A має свою незалежну копію методу функції "x". Тоді як використання "прототипу" означатиме, що кожен екземпляр класу A буде використовувати одну і ту ж копію методу "x".
Ось якийсь код, щоб показати цю тонку різницю:
// x is a method assigned to the object using "this"
var A = function () {
this.x = function () { alert('A'); };
};
A.prototype.updateX = function( value ) {
this.x = function() { alert( value ); }
};
var a1 = new A();
var a2 = new A();
a1.x(); // Displays 'A'
a2.x(); // Also displays 'A'
a1.updateX('Z');
a1.x(); // Displays 'Z'
a2.x(); // Still displays 'A'
// Here x is a method assigned to the object using "prototype"
var B = function () { };
B.prototype.x = function () { alert('B'); };
B.prototype.updateX = function( value ) {
B.prototype.x = function() { alert( value ); }
}
var b1 = new B();
var b2 = new B();
b1.x(); // Displays 'B'
b2.x(); // Also displays 'B'
b1.updateX('Y');
b1.x(); // Displays 'Y'
b2.x(); // Also displays 'Y' because by using prototype we have changed it for all instances
Як уже згадували інші, існують різні причини вибору того чи іншого методу. Мій зразок покликаний чітко продемонструвати різницю.
this
об'єкта, який є власником методу. тобто метод не має об'єкта, який є його власником. У цьому випадку є this
об'єкт, як показано в прикладі класу А.
Візьміть ці 2 приклади:
var A = function() { this.hey = function() { alert('from A') } };
vs.
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
Більшість людей тут (особливо відповіді з найвищим рейтингом) намагалися пояснити, чим вони відрізняються, не пояснюючи ЧОМУ. Я думаю, що це неправильно, і якщо спочатку ви зрозумієте основи, різниця стане очевидною. Спробуємо спочатку пояснити основи ...
а) Функція - це об'єкт у JavaScript. КОЖЕН об’єкт у JavaScript отримує внутрішню властивість (тобто ви не можете отримати доступ до нього, як і інші властивості, за винятком, можливо, у браузерах, як Chrome), які часто називають __proto__
(ви можете фактично вводити anyObject.__proto__
Chrome, щоб побачити, на що він посилається. Це просто те , властивість, нічого більше. Властивість у JavaScript = змінна всередині об'єкта, нічого більше. Що роблять змінні? Вони вказують на речі.
То на що вказує ця __proto__
властивість? Ну зазвичай інший об’єкт (ми пояснимо, чому пізніше). Єдиний спосіб змусити JavaScript для __proto__
властивості НЕ вказувати на інший об’єкт - це використовувати var newObj = Object.create(null)
. Навіть якщо ви це зробите, __proto__
властивість STILL існує як властивість об'єкта, просто воно не вказує на інший об'єкт, на який він вказує null
.
Ось де більшість людей плутаються:
Коли ви створюєте нову функцію в JavaScript (що також є об'єктом, пам’ятаєте?), В момент її визначення JavaScript автоматично створює нову властивість цієї функції, яка називається prototype
. Спробуй це:
var A = [];
A.prototype // undefined
A = function() {}
A.prototype // {} // got created when function() {} was defined
A.prototype
ВІДПОВІДНО від __proto__
готелю. У нашому прикладі "A" тепер має ДВА властивості, які називаються "прототип" та __proto__
. Це велика плутанина для людей. prototype
а __proto__
властивості жодним чином не пов'язані, вони є окремими речами, що вказують на окремі значення.
Вам може бути цікаво: Чому JavaScript має __proto__
властивість, створену для кожного об'єкта? Ну, одне слово: делегація . Коли ви викликаєте властивість на об'єкті, а об'єкт його не має, тоді JavaScript шукає об'єкт, на який посилається, __proto__
щоб побачити, чи може він його мати. Якщо його немає, то він переглядає __proto__
властивість цього об'єкта і так далі ... поки ланцюг не закінчиться. Таким чином називається прототип ланцюга . Звичайно, якщо __proto__
не вказує на об’єкт, а замість цього вказує на велику null
удачу, JavaScript це усвідомлює і поверне вам undefined
власність.
Вам також може бути цікаво, чому JavaScript створює властивість, викликану prototype
функцією, коли ви визначаєте функцію? Тому що він намагається вас обдурити, так обдурити, що це працює як мови на основі класу.
Давайте продовжимо наш приклад і створимо "об'єкт" з A
:
var a1 = new A();
Щось відбувається на задньому плані, коли ця річ сталася. a1
це звичайна змінна, якій було призначено новий, порожній об'єкт.
Те, що ви використовували оператор new
перед викликом функції, A()
зробило щось ДОПОМОГЛЕ у фоновому режимі. new
Ключове слово створюється новий об'єкт , який в даний час заслання a1
і цей об'єкт порожній. Ось, що відбувається додатково:
Ми говорили, що в кожному визначенні функції створюється нова властивість, яка називається prototype
(до якої ви можете отримати доступ до неї, на відміну від __proto__
властивості)? Що ж, ця власність використовується зараз.
Отже, ми зараз в точці, де у нас є свіжоспечений порожній a1
предмет. Ми говорили, що всі об’єкти в JavaScript мають внутрішню __proto__
властивість, яка вказує на щось ( a1
також є), будь то нульовий або інший об'єкт. Те , що new
оператор робить те , що він встановлює , що __proto__
властивість точки до функції в prototype
власність. Прочитайте ще раз. В основному це:
a1.__proto__ = A.prototype;
Ми говорили, що A.prototype
це не що інше, як порожній об’єкт (якщо тільки ми не змінимо його на щось інше, перш ніж визначати a1
). Отже, в основному a1.__proto__
вказує на те саме, на що A.prototype
вказує, що є тим порожнім об'єктом. Вони обоє вказують на той самий об'єкт, який був створений, коли трапився цей рядок:
A = function() {} // JS: cool. let's also create A.prototype pointing to empty {}
Тепер відбувається інша річ, коли var a1 = new A()
оператор обробляється. В основному A()
виконується, і якщо A щось подібне:
var A = function() { this.hey = function() { alert('from A') } };
Все те, що function() { }
знаходиться всередині , збирається виконати. Коли ви досягнете this.hey..
лінії, this
буде змінено на a1
та ви отримаєте це:
a1.hey = function() { alert('from A') }
Я не буду висвітлювати, чому this
зміни, a1
але це чудова відповідь, щоб дізнатися більше.
Отже, підсумовуючи, у вас var a1 = new A()
на задньому плані три речі:
a1
.a1 = {}
a1.__proto__
властивість призначається вказувати на те саме, що і на A.prototype
точки (інший порожній об'єкт {})
Функція A()
виконується за this
допомогою нового, порожнього об'єкта, створеного на кроці 1 (прочитайте відповідь, на яку я посилався вище, чому this
змінюється a1
)
Тепер спробуємо створити інший об’єкт:
var a2 = new A();
Кроки 1,2,3 повторяться. Ви щось помічаєте? Ключове слово - повтор. Крок 1: a2
буде новий порожній об'єкт, крок 2: його __proto__
властивість буде вказувати на те саме, що A.prototype
вказує на, а головне, крок 3: функція A()
ПРОСТО виконується, що означає, що a2
отримає hey
властивість, що містить функцію. a1
і a2
мають два названих роздільних властивостей, hey
які вказують на 2 СЕПАРАТНІ функції! Тепер ми маємо дублюючі функції у двох і тих же різних об'єктах, що роблять те саме, ой ... Ви можете уявити наслідки для пам'яті цього, якщо у нас 1000 об'єктів, створених за new A
, після того, як всі декларації функцій займають більше пам'яті, ніж щось на зразок числа 2. Отже як нам це запобігти?
Пам'ятайте, чому __proto__
властивість існує на кожному об'єкті? Отже, якщо ви отримаєте yoMan
властивість на a1
(яке не існує), його __proto__
властивість буде проконсультуватися, що, якщо це об’єкт (і в більшості випадків це є), він перевірить, чи містить він yoMan
, а якщо його немає, він звернеться до цього об'єкта __proto__
тощо. Якщо це зробити, він візьме це значення властивості і відобразить його вам.
Тож хтось вирішив використати цей факт + той факт, що коли ви створюєте a1
, його __proto__
властивість вказує на той самий (порожній) об’єкт, який A.prototype
вказує і робить це:
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
Класно! Тепер, коли ви створюєте a1
, він знову проходить усі 3 вищевказані кроки, а на кроці 3 він нічого не робить, оскільки function A()
нічого не може виконати. А якщо ми:
a1.hey
Він побачить, що a1
він не містить, hey
і перевірить його __proto__
об’єкт властивості, щоб побачити, чи є у нього, що є випадком.
За допомогою цього підходу ми усуваємо частину з кроку 3, де функції дублюються при кожному створенні нового об'єкта. Замість того , щоб a1
і a2
наявність окремого hey
майна, в даний час ніхто з них не має його. Який, мабуть, ви вже зрозуміли самі. Це приємна річ ... якщо ви розумієте, __proto__
і Function.prototype
такі питання будуть досить очевидними.
ПРИМІТКА. Деякі люди, як правило, не називають внутрішню властивість прототипу, тому __proto__
я використовував це ім'я через пост, щоб чітко відрізнити Functional.prototype
властивість як дві різні речі.
__proto__
і .prototype
це абсолютно різні речі.
У більшості випадків вони по суті однакові, але друга версія економить пам'ять, оскільки існує лише один екземпляр функції замість окремої функції для кожного об'єкта.
Підставою для використання першої форми є доступ до "приватних членів". Наприклад:
var A = function () {
var private_var = ...;
this.x = function () {
return private_var;
};
this.setX = function (new_x) {
private_var = new_x;
};
};
Через правила розміщення Javascript, private_var доступний функції, призначеній для цього.x, але не за межами об'єкта.
Перший приклад змінює інтерфейс лише для цього об’єкта. Другий приклад змінює інтерфейс для всіх об'єктів цього класу.
x
доступною для всіх об'єктів, прототипу яких призначений новий екземпляр A:function B () {}; B.prototype = new A(); var b = new B(); b.x() // Will call A.x if A is defined by first example;
Кінцева проблема використання this
замість цього prototype
полягає в тому, що при переосмисленні методу конструктор базового класу все ще буде посилатися на метод, що переосмислюється. Врахуйте це:
BaseClass = function() {
var text = null;
this.setText = function(value) {
text = value + " BaseClass!";
};
this.getText = function() {
return text;
};
this.setText("Hello"); // This always calls BaseClass.setText()
};
SubClass = function() {
// setText is not overridden yet,
// so the constructor calls the superclass' method
BaseClass.call(this);
// Keeping a reference to the superclass' method
var super_setText = this.setText;
// Overriding
this.setText = function(value) {
super_setText.call(this, "SubClass says: " + value);
};
};
SubClass.prototype = new BaseClass();
var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!
subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
проти:
BaseClass = function() {
this.setText("Hello"); // This calls the overridden method
};
BaseClass.prototype.setText = function(value) {
this.text = value + " BaseClass!";
};
BaseClass.prototype.getText = function() {
return this.text;
};
SubClass = function() {
// setText is already overridden, so this works as expected
BaseClass.call(this);
};
SubClass.prototype = new BaseClass();
SubClass.prototype.setText = function(value) {
BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};
var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
Якщо ви вважаєте, що це не проблема, то це залежить від того, чи зможете ви жити без приватних змінних, і чи достатньо досвідчений ви, щоб дізнатися про витік, коли його побачите. Також незручно вводити логіку конструктора після визначень методу незручно.
var A = function (param1) {
var privateVar = null; // Private variable
// Calling this.setPrivateVar(param1) here would be an error
this.setPrivateVar = function (value) {
privateVar = value;
console.log("setPrivateVar value set to: " + value);
// param1 is still here, possible memory leak
console.log("setPrivateVar has param1: " + param1);
};
// The constructor logic starts here possibly after
// many lines of code that define methods
this.setPrivateVar(param1); // This is valid
};
var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0
a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0
проти:
var A = function (param1) {
this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
this.publicVar = value; // No private variable
};
var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1
Кожен об'єкт пов'язаний з об'єктом-прототипом. При спробі отримати доступ до властивості, яка не існує, JavaScript перегляне об’єкт-прототип об'єкта для цього властивості та поверне його, якщо він існує.
prototype
Властивість функції конструктора відноситься до об'єкту прототипу всіх примірників , створених з цією функцією при використанні new
.
У першому прикладі ви додаєте властивість x
до кожного екземпляра, створеного за допомогою A
функції.
var A = function () {
this.x = function () {
//do something
};
};
var a = new A(); // constructor function gets executed
// newly created object gets an 'x' property
// which is a function
a.x(); // and can be called like this
У другому прикладі ви додаєте властивість до об'єкта-прототипу, на який A
вказують усі створені екземпляри .
var A = function () { };
A.prototype.x = function () {
//do something
};
var a = new A(); // constructor function gets executed
// which does nothing in this example
a.x(); // you are trying to access the 'x' property of an instance of 'A'
// which does not exist
// so JavaScript looks for that property in the prototype object
// that was defined using the 'prototype' property of the constructor
На закінчення, у першому прикладі копія функції призначається кожному екземпляру . У другому прикладі одна копія функції поділяється всіма екземплярами .
Яка різниця? => Багато
Я думаю, що this
версія використовується для включення інкапсуляції, тобто приховування даних. Це допомагає маніпулювати приватними змінними.
Розглянемо наступний приклад:
var AdultPerson = function() {
var age;
this.setAge = function(val) {
// some housekeeping
age = val >= 18 && val;
};
this.getAge = function() {
return age;
};
this.isValid = function() {
return !!age;
};
};
Тепер prototype
структуру можна застосувати наступним чином:
Різні дорослі мають різний вік, але всі дорослі отримують однакові права.
Отже, ми додаємо його за допомогою прототипу, а не цього.
AdultPerson.prototype.getRights = function() {
// Should be valid
return this.isValid() && ['Booze', 'Drive'];
};
Давайте розглянемо реалізацію зараз.
var p1 = new AdultPerson;
p1.setAge(12); // ( age = false )
console.log(p1.getRights()); // false ( Kid alert! )
p1.setAge(19); // ( age = 19 )
console.log(p1.getRights()); // ['Booze', 'Drive'] ( Welcome AdultPerson )
var p2 = new AdultPerson;
p2.setAge(45);
console.log(p2.getRights()); // The same getRights() method, *** not a new copy of it ***
Сподіваюсь, це допомагає.
Прототип - шаблон класу; що стосується всіх його майбутніх примірників. Тоді як це конкретний екземпляр об'єкта.
Я знаю, що на це відповіли на смерть, але я хотів би показати фактичний приклад різниці швидкостей.
Тут ми створюємо 2 000 000 нових об’єктів print
методом у Chrome. Ми зберігаємо кожен об’єкт у масиві. Одяг print
на прототип займає приблизно 1/2, ніж довгий.
Дозвольте дати вам більш вичерпну відповідь, яку я дізнався під час навчального курсу JavaScript.
Більшість відповідей вже згадували про різницю, тобто при прототипуванні функції поділяються з усіма (майбутніми) екземплярами. Тоді як оголошення функції в класі створить копію для кожного примірника.
Взагалі немає правильного чи неправильного, це більше питання смаку чи дизайнерського рішення залежно від ваших вимог. Проте прототип - це техніка, яка використовується для розробки об'єктно-орієнтованим чином, як я сподіваюся, ви побачите в кінці цієї відповіді.
У вашому запитанні ви показали дві схеми. Я спробую пояснити ще два і спробую пояснити відмінності, якщо це доречно. Не соромтеся редагувати / розширювати. У всіх прикладах мова йде про автомобільний об’єкт, який має місце розташування і може рухатися.
Не впевнений, чи ця модель досі актуальна, але вона існує. І про це добре знати. Ви просто передаєте об'єкт і властивість функції декоратора. Декоратор повертає об’єкт властивістю та методом.
var carlike = function(obj, loc) {
obj.loc = loc;
obj.move = function() {
obj.loc++;
};
return obj;
};
var amy = carlike({}, 1);
amy.move();
var ben = carlike({}, 9);
ben.move();
Функція в JavaScript - це спеціалізований об'єкт. Окрім виклику, функція може зберігати властивості, як і будь-який інший об’єкт.
В цьому випадку Car
є функцією ( також думає , об'єкт ) , який може бути викликаний , як ви звикли робити. Він має властивість methods
(яка є об'єктом з move
функцією). Коли Car
викликається extend
функція, викликається функція, яка робить деяку магію, і розширює Car
функцію (об'єкт мислить) методами, визначеними всередині methods
.
Цей приклад, хоча і інший, наближається до першого прикладу у питанні.
var Car = function(loc) {
var obj = {loc: loc};
extend(obj, Car.methods);
return obj;
};
Car.methods = {
move : function() {
this.loc++;
}
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
Перші два шаблони дозволяють обговорити використання методів визначення загальних методів або використання методів, визначених вбудовано в тілі конструктора. В обох випадках кожен екземпляр має свою move
функцію.
Прототипний шаблон не піддається тому самому дослідженню, тому що обмін функціями через делегування прототипу є самою метою для прототипного шаблону. Як зазначали інші, очікується, що він покращить пам'ять.
Однак є один момент, який цікаво знати: кожен prototype
об'єкт має властивість зручності constructor
, яка вказує на функцію (мислити об’єкт), до якої він приєднався.
Щодо останніх трьох рядків:
У цьому прикладі Car
посилання на prototype
об'єкт, який пов'язує через constructor
до Car
себе, тобто Car.prototype.constructor
це Car
саме по собі. Це дозволяє зрозуміти, яка конструкторська функція побудувала певний об’єкт.
amy.constructor
пошук не вдається, і, таким чином, делегується до Car.prototype
, що має властивість конструктора. Так і amy.constructor
є Car
.
Крім того, amy
є instanceof
Car
. instanceof
Оператор працює, бачачи , якщо об'єкт - прототип правого операнда ( Car
) можна знайти в будь-якому місці в прототипі лівого операнда ( amy
) ланцюга.
var Car = function(loc) {
var obj = Object.create(Car.prototype);
obj.loc = loc;
return obj;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car);
Деякі розробники на початку можна плутати. Дивіться приклад нижче:
var Dog = function() {
return {legs: 4, bark: alert};
};
var fido = Dog();
console.log(fido instanceof Dog);
У instanceof
оператор повертається false
, тому що Dog
«прототип сек не може бути знайдений де - небудь в fido
" S ланцюга прототипів. fido
це простий об'єкт, який створюється з об'єктом буквально, тобто він просто делегується Object.prototype
.
Це дійсно просто ще одна форма прототипного шаблону у спрощеному вигляді та більш звична для тих, хто програмує на Java, наприклад, оскільки він використовує new
конструктор.
Це робиться так само, як і в прототипному малюнку, це просто синтаксичний цукор поверх прототипного шаблону.
Однак головна відмінність полягає в тому, що в двигунах JavaScript існують оптимізації, які застосовуються лише при використанні псевдокласичного шаблону. Подумайте про псевдокласичну схему, ймовірно, більш швидку версію прототипного шаблону; об'єктні відносини в обох прикладах однакові.
var Car = function(loc) {
this.loc = loc;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = new Car(1);
amy.move();
var ben = new Car(9);
ben.move();
Нарешті, не повинно бути надто складно зрозуміти, як можна виконати об’єктно-орієнтоване програмування. Є два розділи.
Один розділ, який визначає загальні властивості / методи в прототипі (ланцюзі).
І ще один розділ, де ви ставите визначення, які відрізняють об'єкти один від одного ( loc
змінна в прикладах).
Саме це дозволяє нам застосовувати такі поняття, як суперклас або підклас у JavaScript.
Не соромтеся додавати чи редагувати. Ще раз повніше я міг би зробити це вікі спільноти.
Я вважаю, що @Matthew Crumley має рацію. Вони функціонально , якщо не структурно, рівнозначні. Якщо ви використовуєте Firebug для перегляду об’єктів, створених за допомогою new
, ви можете бачити, що вони однакові. Однак моїм уподобанням було б таке. Я здогадуюсь, що це просто більше схоже на те, до чого я звик у C # / Java. Тобто визначте клас, визначте поля, конструктор та методи.
var A = function() {};
A.prototype = {
_instance_var: 0,
initialize: function(v) { this._instance_var = v; },
x: function() { alert(this._instance_var); }
};
EDIT Не означав, що область змінної була приватною, я просто намагався проілюструвати, як я визначаю свої класи в JavaScript. Ім'я змінної було змінено, щоб відобразити це.
initialize
і x methods do not refer to the
_instance_var` в A
екземплярі, але до глобальної. Використовуйте, this._instance_var
якщо ви мали намір використовувати _instance_var
властивість A
екземпляра.
Як обговорюється в інших відповідях, це дійсно врахування продуктивності, оскільки функція в прототипі поділяється з усіма інстанціями, а не функцією, що створюється для кожної інстанції.
Я зібрав jsperf, щоб показати це. Існує різка різниця у часі, необхідному для інстанціювання класу, хоча це дійсно актуально лише у тому випадку, коли ви робите багато екземплярів.