Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 4 of 4
  1. #1
    New Coder
    Join Date
    Feb 2006
    Posts
    39
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Attempting to understanding privileged methods and Object.create

    This is in reference to Crockford's articles found here:

    http://javascript.crockford.com/prototypal.html
    http://javascript.crockford.com/private.html

    I'm attempting to understand the use of privileged methods when used with Object.create. I put together a quick demo (code below) that shows what happens when I use Object.create to create a new object based on one that has a privileged method. The outcome is not pleasant, as changing the value in the first object also changes it in the second. Unless I am reading Crockford's articles incorrectly, this makes Object.create almost useless for anything but objects that have only public members.

    I've seen many JavaScript programmers use closures extensively to create private members, and that still holds to be a good programming practice. However I still can't find an elegant way to create inheritance in combination with closures in JavaScript, given downfalls such as the one I mentioned above.

    With all of that said I still think Crockford has a nice way of programming, creating factory functions that produce objects, staying away from the prototype property and making the language look more functional.

    Here's the code to demonstrate what I'm referring to. Firebug needs to be enabled to view the console.debug output, otherwise convert them to alerts.

    Code:
    if (typeof Object.create !== 'function') {
        Object.create = function (o) {
            function F() {}
            F.prototype = o;
            return new F();
        };
    }
    
    var o = (function() {
    	var msg = "hi";
    	
    	return {
    		msg: function(m) {
    			if (m === undefined) {
    				return msg;
    			}
    			
    			msg = m;
    		}
    	};
    })();
    
    var foo = Object.create(o);
    var bar = Object.create(foo);
    
    console.debug(foo.msg());	// "hi"
    
    foo.msg("what?");
    
    console.debug(foo.msg());	// "what?"
    console.debug(bar.msg());	// "what?"

  • #2
    Regular Coder
    Join Date
    Feb 2009
    Location
    NJ, USA
    Posts
    476
    Thanks
    2
    Thanked 70 Times in 69 Posts
    Ok, the problem is that you are creating a closure only once in your code, and returning an object to be placed into variable o. So even though Object.create() is called twice, the function (method) that you receive in each object is actually the same exact function, and refers to the same exact msg variable. That's why changing it in one object makes it change in the other object - they change the same variable.

    In other words, that outer anonymous function runs only once as the code gets executed, and returns an object with an inner function. The inner function has a reference to the variable msg in it (via closure), no matter how many times you call it.



    I've been programming in JavaScript for 10 years now, and I gotta tell ya, I'm not particularly a fan of Crockford's tutorials. Although they bring in some ways to emulate data hiding in an attempt for better Object Oriented code in JavaScript, they're:

    1. Not very easy to understand, especially when starting out.
    2. Implementing these techniques usually isn't even feasible in practice, especially when using prototype chained inheritance hierarchies - JavaScript's emulation of class based inheritance.
    3. If you actually do want to use "private" and "privileged" methods (which can only be done when not creating an inheritance hierarchy), your code is not as efficient with memory. The reason for this is because a class's methods need to literally be duplicated in memory for each instance of the class. 1000 instances of a class == 1000 duplicates of each method of the class. Now, when methods are put on the prototype of a class, as is usually done, they are shared by all instances of the class. However, they then can not access any "private" variables via closure.

    Therefore, I feel that Doug leads a lot of new JavaScript programmers astray with false hopes of achieving true information hiding in JavaScript. It's just one of those things that sounds great on paper, but isn't practical in the real world.

    Overall from my experience, the concept of an actual private variable in JavaScript is very rarely used, except for singleton classes (classes that can only have one instance). Otherwise, most programmers usually just denote a private variable in some way (usually with a prefixed underscore), even though they can really be accessed just as public variables.



    However, if you're interested, this code would in fact emulate a private variable and privileged methods (even though it would suffer from the inefficiency of memory that I described above):
    Code:
    function Person() {
        var name = "";
        
        this.setName = function( newName ) {
            name = newName;
        }
        
        this.getName = function() {
            return name;
        }
    }
    
    
    var p1 = new Person();
    p1.setName( "Gjslick" );
    
    var p2 = new Person();
    p2.setName( "wyrd33" );
    
    
    console.debug( p1.getName() ); // displays "Gjslick"
    console.debug( p2.getName() ); // displays "wyrd33"
    This works because completely new setName() and getName() functions are created for each instance of the Person class. Therefore, each function (method) has a closure with a reference to their own private variable, name.

    Hope that helps you understand a bit.

    -Greg
    Last edited by Gjslick; 04-14-2010 at 03:14 AM.

  • #3
    New Coder
    Join Date
    Feb 2006
    Posts
    39
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I appreciate you taking the time to respond.

    However I believe I may not have explained myself well enough. I'm attempting to better understand Crockford's prototypal way of thinking, as opposed to the classical way that most folks (your code as an example) think and code now. I'm doing this for purely exploration reasons in an attempt to better understand just how far you can actually take JavaScript. His book and latest talks (YUI theater if you're interested) have intrigued me to explore this style of programming.

    With that said, after researching further and finding other samples (Pro JavaScript Design Patterns book as one of them) of prototypal programming, I've come to the stark realization that it comes with quite a few pitfalls that Crockford always seems to neglect in his lectures. The example in my original post shows one of them. A trivial task (your example) using classical approach, but nearly impossible with the prototypal approach.

    So in other words, yes you're right. It may not be feasible, it may not be efficient, and Crockford may be off his rocker. But darn is it fun to explore.

  • #4
    Regular Coder
    Join Date
    Feb 2009
    Location
    NJ, USA
    Posts
    476
    Thanks
    2
    Thanked 70 Times in 69 Posts
    Well, then you definitely came to the right place then to learn! And that's great that you actually do want to learn too. Many people just want to copy and paste some scripts and call it a day.

    I guess that I originally figured that because you were talking about data hiding and private and privileged members, that I should discuss the pitfalls of that topic instead of anything else though And yes, that's too bad that Crockford really doesn't go into discussing those pitfalls in his lectures. It all looks good and dandy until you try to implement it, lol.

    But prototypal inheritance was actually the method of inheritance that the creator of JavaScript had intended for the language. So it's not particularly just Crockford's way of thinking, it's the ECMAScript way of thinking You can emulate other forms, even multiple inheritance, but prototype chaining is really the way it's done. But I do agree completely that the other methods are fun and interesting to explore and understand. How do you think that I know about all of their pitfalls and such in the first place?

    What I do recommend though is picking up the book JavaScript: The Definitive Guide. After years of misunderstanding, this was the book that finally shed the light for me on the subject of how the prototype itself, and the process of prototype chaining actually works. I believe the 5th edition is the latest, and the book really is the end-all-be-all on JavaScript, even though 5th edition is getting to be a few years old now. You'll want to read the chapter "Classes, Constructors, and Prototypes." (Although I personally find it useful to call them "classes", he just uses the term "class" for lack of a better one. Really they are "Constructor Functions.")



    However, if you want a simple example for now, try this out:

    For copying/pasting:
    Code:
    function A() {}
    A.prototype.var1 = "Var1 - Located in class A";
    
    function B() {}
    B.prototype = new A();    // we set the prototype of class B to an  *object* of class A. This sets up the prototype chain
    B.prototype.var2 = "Var2 - Located in class B";
    
    
    
    var obj = new B();
    alert( obj.var2 );    // taken from B's prototype
    alert( obj.var1 );    // taken from A's prototype - "inherited"
    With line numbers:
    Code:
    01) function A() {}
    02) A.prototype.var1 = "Var1 - Located in class A";
    03) 
    04) function B() {}
    05) B.prototype = new A();    // we set the prototype of class B to an *object* of class A. This sets up the prototype chain
    06) B.prototype.var2 = "Var2 - Located in class B";
    07) 
    08) 
    09) 
    10) var obj = new B();
    11) 
    12) alert( obj.var2 );    // taken from B's prototype
    13) alert( obj.var1 );    // taken from A's prototype - "inherited"
    Basically how it works is this: When property var2 of object obj is requested (line 12), a lookup is performed. So for that first alert, the lookup goes like this:

    1. Is var2 a direct property of obj itself? No, check the prototype.
    2. Is var2 defined in the prototype of the object associated with obj? Yes, return that.


    For the second alert on line 13, requesting obj.var1, the lookup goes like this:

    1. Is var1 a direct property of obj itself? No, check the prototype.
    2. Is var1 defined in the prototype of the object associated with obj? No -- However our prototype itself has a prototype, check that. (The prototype itself has a prototype because an object was set to it. That object itself has a prototype. line 5).
    3. Is var1 defined in the next prototype? Yes it is, return that.

    Hence, var1 is "inherited" from A, even though obj is an object of type B. Of course, it's not really inherited in the classical sense, but more that it's "found." Any addition of a var1 property to B's prototype will actually hide the inherited member from A.



    I hope that helps for you to understand it all a little more though! I'm sure there are plenty of other examples online as well. But I definitely recommend picking up that book; it's really one of the best ones I've ever bought (I have 4, lol).

    And let me know if you need any more explanation or want to understand anything else



    All the best,

    Greg


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •