4

Javascript & ldquo; Private & rdquo; Vs properties of the instance

 2 years ago
source link: https://www.codesd.com/item/javascript-private-vs-properties-of-the-instance.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Javascript & ldquo; Private & rdquo; Vs properties of the instance

advertisements

I'm doing some Javascript R&D and, while I've read Javascript: The Definitive Guide and Javascript Object Oriented Programming, I'm still having minor issues getting my head out of class based OOP and into lexical, object based OOP.

I love modules. Namespaces, subclasses and interfaces. w00t. Here's what I'm playing with:

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")
        }
    }
})

Im trying to find the best way to modularize my code (and understand prototyping) and separate everything out. Notice Globe is a function that needs to be instantiated with new, Umbrella is a singleton and already declared, Igloo uses something I thought about at work today, and seems to be working as well as I'd hoped, and House is another Iglooesque function for testing.

The output of this is:

Globe
unavailable
Igloo
My House

So far so good. The Globe prototype has to be declared outside the Classes object for syntax reasons, Umbrella can't accept due to it already existing (or instantiated or... dunno the "right" term for this one), and Igloo has some closure that declares it for you.

HOWEVER...

If I were to change it to:

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")
        }
    }
})

and make this.name into _name (the "private" property), it doesn't work, and instead outputs:

My House
unavailable
My House
My House

Would someone be kind enough to explain this one? Obviously _name is being overwritted upon each iteration and not reading the object's property of which it's attached.

This all seems a little too verbose needing this and kinda weird IMO.

Thanks :)


You declare a global variable. It is available from anywhere in your code after declaration of this. Wherever you request to _name(more closely window._name) you will receive every time a global. In your case was replaced _name in each function. Last function is House and there has been set to "My House"

Declaration of "private" (local) variables must be with var statement.

Check this out:

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

Should be:

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




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK