Подтвердить что ты не робот

Лучший подход к переменным-членам в объектно-ориентированном javascript?

Это вопрос, который я только что опубликовал. Мне интересно, как вы все обрабатываете переменные-члены в javascript-кланах при использовании MyClass.prototype для определения методов.

Если вы определяете все методы в функции конструктора:

function MyClass(){
 this.myMethod = function(){}
}

Вы можете очень хорошо объявить переменные-члены и получить доступ к ним из ваших методов:

function MyClass(){
 var myVar = "hello";
 this.myMethod = function(){
  alert(myVar);
 }
}

При использовании метода Object.prototype вы теряете эту тонкость и должны делать это следующим образом:

function MyClass(){}
MyClass.prototype.myVar = "hello";
MyClass.prototype.myMethod = function(){alert(this.hello)};

Я не сумасшедший о необходимости писать "this" каждый раз, когда я обращаюсь к переменной-члену. Я хочу использовать подход Object.prototype для соображений памяти и гибкости, но он кажется намного более неудобным по синтаксису. Это как вы, как правило, работаете?

спасибо,

-Morgan

4b9b3361

Ответ 1

Вы должны преодолеть свое нежелание использовать указатель this для доступа к переменным-членам.

Назначьте переменные-члены в конструкторе, и вы можете получить к ним доступ с помощью прототипов:

function Cat(){
    this.legs = 4;
    this.temperament = 'Apathetic';
    this.sound = 'Meow';
}

Cat.prototype.speak = function(){alert(this.sound)}

var cat = new Cat();
cat.speak();

Да, эти атрибуты объекта общедоступны, но, как сказал бы Гвидо, мы все взрослые здесь. Javascript - это, в конце концов, простой текстовый, слабо типизированный, интерпретируемый язык. Преимущества переменных "private" в этой среде в лучшем случае шатки.

Я говорю только, чтобы быть явным и очевидным о том, как следует обращаться к вашему объекту, а нарушители будут отклоняться от этого на свой страх и риск.

Ответ 2

Видимость атрибутов объекта зависит от того, как вы их объявляете

function Cat( name ) {

    //private variable unique to each instance of Cat
    var privateName = 'Cat_'+Math.floor( Math.random() * 100 );

    //public variable unique to each instance of Cat
    this.givenName = name;

    //this method has access to private variables
    this.sayPrivateName = function() {
        alert( privateName );
    }
}

//this variable is shared by all cats
Cat.prototype.generalName = 'tiddles';

//this method is shared by all cats and has no access to private vars
Cat.prototype.sayname = function( type ) {
    alert( this[type+'Name'] || 'private!' );
}

var vic = new Cat('Victor');
var ellers = new Cat('Elmore');

vic.sayname('general');    //tiddles
vic.sayname('given');      //Victor
vic.sayname('private');    //private - no access
vic.sayPrivateName();      //cat will say its name

ellers.sayname('general');    //tiddles
ellers.sayname('given');      //Elmore
ellers.sayname('private');    //private - no access
ellers.sayPrivateName();      //cat will say its name

Ответ 3

Вы должны использовать прототип для хранения методов, потому что, когда вы найдете 100 методов, они не копируются между экземплярами, а используют один и тот же прототип. Я использую что-то в этих строках:

var myClass = function(){};
myClass.prototype = {
    method1: function(){}
    ,method2: function(){}   
};

Ответ 4

A (не так) небольшое замечание по переменным 'private' при назначении методам прототипу:

Верно, что вы не можете использовать конструктор для создания замыкания по ним, но вы можете, конечно, объединить прототипы с анонимной функцией и получить частные переменные, разделяемые между экземплярами объекта:

function Foo() {}

(function() {
    var sharedPrivateVar;
    Foo.prototype.methodWithAccessToSharedPrivateVar = function() {};
})();

С еще одним сглаживанием вы можете реализовать свои собственные механизмы защиты, например переменные, которые могут быть прочитаны, а не написаны с помощью:

function Foo() {
    this.registerInstance({ bar : 'baz' });
    this.registerInstance = undefined;
}

(function() {
    var store = {}, guid = 0;

    Foo.prototype.registerInstance = function(protectedProperties) {
        this.__guid = ++guid;
        store[this.__guid] = protectedProperties;
    };

    Foo.prototype.getProtectedProperty = function(name) {
        return store[this.__guid][name];
    };

})();

Этот подход не будет страдать от создания расширенного объекта и закрытия, но увеличивает время поиска на небольшую сумму.

Изменить: Вы также должны указать функцию

Foo.prototype.unregisterInstance = function() {
    delete store[this.__guid];
};

В противном случае это хороший способ ввести утечку памяти...

Edit2: Вы также можете обойти необходимость в функции registerInstance() со следующим шаблоном:

Foo = (function() {
    var store = {}, guid = 0;

    function Foo() {
        this.__guid = ++guid;
        store[guid] = { bar : 'baz' };
    }

    Foo.prototype.getBar = function() {
        var privates = store[this.__guid];
        return privates.bar;
    };

    Foo.prototype.destroy = function() {
        delete store[this.__guid];
    };

    return Foo;
})();

Ответ 5

Вы найдете много людей, использующих

function name()
{
    var m_var = null;
    var privateMethod = function() { }
    this.PublicMethod = function() { }
}

Включая меня. Я склонен не писать огромные классы JS, и этот синтаксис довольно легко писать, а также позволяет использовать частные методы/переменные.

ИЗМЕНИТЬ

Итак, вы говорите мне, что использование XML для SOAP-пакетов просто для облегчения отладки на один шаг - это хорошо (хотя XML тратит BUNCH пространства и полосы пропускания и разбора времени), но добавление нескольких байтов на экземпляр объекта javascript не хорошо, даже если это позволяет нам использовать некоторые из фундаментальных концепций ОО, которые должны существовать на языке с самого начала?

Хм...

(для моего комментария XML читайте комментарии для: REST URI и операции над объектом, который можно прокомментировать, помечен, оценен и т.д.)