Функции экземпляра JavaScript в сравнении с функциями прототипа
Возможный дубликат:
Использование "прототипа" против "этого" в Javascript?
Мое понимание различных функций JavaScript выглядит следующим образом:
function MyObj() {
this.propOne = true;
this.publicInstanceFunc = function() {
if (propOne)
return 'public instance function';
}
function privateFunc() {
return 'private function only visible inside this constructor';
}
}
MyObj.prototype.protoFunc = function() {
if (this.propOne)
return 'prototype function shared amongst all instances of MyObj';
}
- Правильны ли они?
- В каких случаях следует ставить функции на прототипе (например,
protoFunc
) и в конструкторе (например, publicInstanceFunc
)?
- Использует
this
правильный способ доступа к свойствам внутри функций прототипа?
Ответы
Ответ 1
Фактически вы можете добавить еще один уровень привилегий, обернув все это в функцию самоисполнения:
var MyObj = (function() { // scoping
var privateSharedVar = 'foo';
function privateSharedFunction() {
// has access to privateSharedVar
// may also access publicSharedVar via explicit MyObj.prototype
// can't be called via this
}
function MyObj() { // constructor
var privateInstanceVar = 'bar';
this.publicInstanceVar = 'baz';
function privateInstanceFunction() {
// has access to all vars
// can't be called via this
};
this.publicInstanceMethod = function() {
// has access to all vars
// also known as a privileged method
};
}
MyObj.prototype.publicSharedVar = 'quux';
MyObj.prototype.publicSharedMethod = function() {
// has access to shared and public vars
// canonical way for method creation:
// try to use this as much as possible
};
return MyObj;
})();
Доступ к "общедоступным" свойствам можно получить извне через this
.
По соображениям производительности вам следует избегать того, что я назвал "экземплярами": для каждого из них для каждого экземпляра MyObject
должен быть создан новый функциональный объект, тогда как для одного "общего" метода существует только один функциональный объект.
Ответ 2
Правильны ли они?
Err. Ну, это зависит от того, что вы хотите сделать. В JavaScript не существует принятой канонической модели для реализации наследования типа класса/экземпляра.
Но это:
if (propOne)
Вероятно, ошибка в том, что this.propOne
является свойством объекта owner, тогда как propOne
сам по себе является переменной, которая не была объявлена (по умолчанию это глобальная переменная, но обычно является ошибкой).
В каких случаях следует ставить функции на прототипе (например, protoFunc) и в конструкторе (например, publicInstanceFunc)?
Функция, установленная на прототипе, является той же самой функцией, которая используется для всех объектов. Единственный способ, которым он может решить, к какому экземпляру он принадлежит, - это прочитать "это, когда он вызывается".
Функция, установленная в 'this в конструкторе, является новой функцией для каждого экземпляра MyObj
. Вы можете использовать это как альтернативный способ привязки к объекту владельца на основе замыканий, а не "это", что может сэкономить на выводе материала для привязки функций. Это другой стиль объектной ориентации, который обычно не смешивался с этим стилем.
Ответ 3
1) Да, ваш код прав.
2) Я использую функции, определенные в функции конструктора, когда хочу получить доступ к другим членам, определенным конфиденциально внутри области самой функции конструктора, например, когда вы хотите создать привилегированные методы.
Публичные функции, определенные в функции конструктора, являются более вычислительно дорогостоящими, чем добавление простой функции к прототипу объекта, но они также дают вам большую гибкость.
3) Да, если это свойство является общедоступным, вы можете получить к нему доступ, используя ключевое слово this
внутри расширенной функции прототипа, поскольку this
относится к экземпляру вашего объекта.
Ответ 4
Что касается второй точки, вы расширяете прототип, чтобы все уже созданные объекты получили новый метод.
Кроме того, вы можете добавлять методы к встроенным объектам (например, добавление trim()
в string
).