Javascript "частные" против свойств экземпляра - PullRequest
4 голосов
/ 12 января 2012

Я занимаюсь исследованиями и разработками Javascript, и, хотя я прочитал Javascript: Полное руководство и Объектно-ориентированное программирование Javascript , у меня все еще есть небольшие проблемы с получением моей головывне класса на основе ООП и в лексическом, объектно-ориентированном ООП.

Я люблю модули.Пространства имен, подклассы и интерфейсы.w00t.Вот с чем я играю:

var Classes = {
    _proto : {
        whatAreYou : function(){
            return this.name;
        }
    },
    Globe : function(){
        this.name = "Globe"
    },
    Umbrella : new function(){
        this.name = "Umbrella"
    }(),
    Igloo : function(){
        function Igloo(madeOf){
            this.name = "Igloo"
            _material = madeOf;
        }
        // Igloo specific
        Igloo.prototype = {
            getMaterial : function(){
                return _material;
            }
        }
        // the rest
        for(var p in Classes._proto){
            Igloo.prototype[p] = Classes._proto[p]
        }
        return new Igloo(arguments[0]);
    },
    House : function(){
        function House(){
            this.name = "My House"
        }
        House.prototype = Classes._proto
        return new House()
    }
}
Classes.Globe.prototype = Classes._proto
Classes.Umbrella.prototype = Classes._proto

$(document).ready(function(){    
    var globe, umb, igloo, house;

    globe     = new Classes.Globe();
    umb       = Classes.Umbrella;
    igloo     = new Classes.Igloo("Ice");
    house     = new Classes.House();

    var objects = [globe, umb, igloo, house]

    for(var i = 0, len = objects.length; i < len; i++){
        var me = objects[i];
        if("whatAreYou" in me){
            console.log(me.whatAreYou())
        }else{
            console.warn("unavailable")
        }
    }
})

Я пытаюсь найти лучший способ для модуляции своего кода (и понимания прототипирования) и отделить все вокруг.Обратите внимание, что Globe - это функция, для которой нужно создать экземпляр с new, Umbrella - это одиночный и уже объявленный, Igloo использует то, о чем я думал сегодня на работе, и, кажется, работает так же, как янадеюсь, и House - еще одна иглуская функция для тестирования.

Вывод этого:

Globe
unavailable
Igloo
My House

Пока все хорошо.Прототип Globe должен быть объявлен вне объекта Classes по причинам синтаксиса, Umbrella не может принять его из-за того, что он уже существует (или создан или ... не знаю, «правильный» термин для этого), и у Igloo есть некоторое закрытие, которое объявляетэто для вас.

ОДНАКО ...

Если бы я изменил его на:

var Classes = {
    _proto : {
        whatAreYou : function(){
            return _name;
        }
    },
    Globe : function(){
        _name = "Globe"
    },
    Umbrella : new function(){
        _name = "Umbrella"
    }(),
    Igloo : function(){
        function Igloo(madeOf){
            _name = "Igloo"
            _material = madeOf;
        }
        // Igloo specific
        Igloo.prototype = {
            getMaterial : function(){
                return _material;
            }
        }
        // the rest
        for(var p in Classes._proto){
            Igloo.prototype[p] = Classes._proto[p]
        }
        return new Igloo(arguments[0]);
    },
    House : function(){
        function House(){
            _name = "My House"
        }
        House.prototype = Classes._proto
        return new House()
    }
}
Classes.Globe.prototype = Classes._proto
Classes.Umbrella.prototype = Classes._proto

$(document).ready(function(){    
    var globe, umb, igloo, house;

    globe     = new Classes.Globe();
    umb       = Classes.Umbrella;
    igloo     = new Classes.Igloo("Ice");
    house     = new Classes.House();

    var objects = [globe, umb, igloo, house]

    for(var i = 0, len = objects.length; i < len; i++){
        var me = objects[i];
        if("whatAreYou" in me){
            console.log(me.whatAreYou())
        }else{
            console.warn("unavailable")
        }
    }
})

и превратил this.name в _name ("private" свойство), оно не работает и вместо этого выдает:

My House
unavailable
My House
My House

Кто-нибудь будет достаточно любезен, чтобы объяснить это?Очевидно, _name перезаписывается при каждой итерации и не читает свойство объекта, к которому он прикреплен.

Все это кажется слишком многословным, требующим this и своего рода странного ИМО.

Спасибо:)

Ответы [ 2 ]

5 голосов
/ 12 января 2012

Вы объявляете глобальную переменную.Он доступен из любого места в вашем коде после объявления этого.Куда бы вы ни попросили _name (точнее window._name), вы будете получать каждый раз, когда вы получаете глобальный.В вашем случае было заменено _name в каждой функции.Последняя функция - House, и для нее установлено значение «Мой дом»

Объявление «частных» (локальных) переменных должно быть с var оператором .

Проверкаэто из:

var foo = function( a ) { 
    _bar = a;
    this.showBar = function() { 
       console.log( _bar );
    }
};
var a = new foo(4);   // _bar ( ie window._bar) is set to 4

a.showBar(); //4


var b = new foo(1); // _bar  is set to 1
a.showBar(); //1
b.showBar(); //1

_bar = 5; // window._bar = 5; 
a.showBar();// 5

Должно быть:

var foo = function( a ) { 

    var _bar = a;
    // _bar is now visibled only from both that function
    // and functions that will create or delegate from this function,
    this.showBar = function() { 
       console.log( _bar );
    };
    this.setBar = function( val ) { 
        _bar = val;
    };
    this.delegateShowBar = function() { 
       return function( ) { 
           console.log( _bar );
       }
    }
};
foo.prototype.whatever = function( ){ 
    //Remember - here don't have access to _bar
};

var a = new foo(4);
a.showBar(); //4

_bar // ReferenceError: _bar is not defined  :)
var b = new foo(1);

a.showBar(); //4
b.showBar(); //1

delegatedShowBar  = a.delegateShowBar();
a.setBar(6);
a.showBar();//6
delegatedShowBar(); // 6
1 голос
/ 12 января 2012

Если вы удалите ключевое слово «this», то имя _ будет находиться в области действия «Globe».

Глядя на ваш код.

var globe, umb, igloo, house;

globe     = new Classes.Globe();
umb       = Classes.Umbrella;
igloo     = new Classes.Igloo("Ice");
house     = new Classes.House();

Наконец дом переопределит значение "_name" в области видимости глобуса именем "Мой дом".

...