какая разница между
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 не устанавливается вызовом, поэтому по умолчанию используется глобальный объект, и выражение this.x
действует window.x
. В результате ссылка на выражение функции в правой части назначается window.x
.
На случай, если:
var A = function () { };
A.prototype.x = function () {
//do something
};
происходит что-то совсем другое. В первой строке переменной A
присваивается ссылка на функцию. В JavaScript все объекты функций по умолчанию имеют свойство prototype , поэтому нет отдельного кода для создания объекта A.prototype .
Во второй строке A.prototype.x назначается ссылка на функцию. Это создаст свойство x, если оно не существует, или назначит новое значение, если оно существует. Таким образом, разница с первым примером, в котором свойство x объекта участвует в выражении.
Другой пример ниже. Это похоже на первый (и, возможно, о чем вы хотели спросить):
var A = new function () {
this.x = function () {
//do something
};
};
В этом примере new
оператор был добавлен перед выражением функции, поэтому функция вызывается как конструктор. При вызове с new
помощью функции this устанавливается ссылка на новый объект, частное [[Prototype]]
свойство которого установлено для ссылки на открытый прототип конструктора . Таким образом, в операторе присваивания x
будет создано свойство для этого нового объекта. При вызове в качестве конструктора функция возвращает свой объект this по умолчанию, поэтому нет необходимости в отдельном return this;
операторе.
Чтобы проверить, что A имеет свойство x :
console.log(A.x) // function () {
// //do something
// };
Это необычное использование new, поскольку единственный способ ссылаться на конструктор - через 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 голосов :-(
"The language is functional"
Вы уверены, что это то, что означает функционал?
A
функцию, а другая половина о неясных и неортодоксальных способах выполнения. что-то простое.
Как говорили другие версии первой версии, использование «this» приводит к тому, что каждый экземпляр класса 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
объект, как показано в классе A в примере.
Возьмите эти 2 примера:
var A = function() { this.hey = function() { alert('from A') } };
против
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» теперь имеет ДВА свойства, называемые «prototype» и __proto__
. Это большая путаница для людей. prototype
и __proto__
свойства никак не связаны, это разные вещи, указывающие на отдельные значения.
Вы можете задаться вопросом: почему JavaScript имеет __proto__
свойство, созданное для каждого отдельного объекта? Ну, одним словом: делегирование . Когда вы вызываете свойство объекта, а у объекта его нет, JavaScript ищет объект, на который ссылается объект, __proto__
чтобы узнать, есть ли у него его. Если у него его нет, то он смотрит на __proto__
свойство этого объекта и так далее ... пока цепочка не закончится. Так называется прототип цепочки . Конечно, если JavaScript __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()
на заднем плане происходят 3 вещи:
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
имеют два названных свойства SEPARATE, 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
такие вопросы будут довольно очевидными.
ПРИМЕЧАНИЕ. Некоторые люди склонны не вызывать внутреннее свойство 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 доступен для функции, назначенной this.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); }
};
РЕДАКТИРОВАТЬ Не имелось в виду, что область действия переменной была закрытой, я просто пытался проиллюстрировать, как я определяю свои классы в javascript. Имя переменной было изменено, чтобы отразить это.
initialize
и x methods do not refer to the
_instance_var` для A
экземпляра, но для глобального. Используйте, this._instance_var
если вы намеревались использовать _instance_var
свойствоA
экземпляра.
Как обсуждалось в других ответах, это действительно соображение производительности, потому что функция в прототипе совместно используется со всеми экземплярами, а не с функцией, создаваемой для каждого экземпляра.
Я собрал jsperf, чтобы показать это. Существует существенное различие во времени, которое требуется для создания экземпляра класса, хотя на самом деле это актуально, только если вы создаете много экземпляров.