Функции экземпляра 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).