www.webdeveloper.com
Results 1 to 4 of 4

Thread: Creating a prototype inside a constructor, and making the "new" keyword optional.

  1. #1
    Join Date
    Nov 2010
    Posts
    86

    Creating a prototype inside a constructor, and making the "new" keyword optional.

    Hi, there are two issues that I think can make javascript objects uglier and harder to organise than they need to be. They are:
    1 - Defining the prototype separate from the constructor function, e.g:
    Code:
    function some_object(name)
    {
        this.name = name;
        this.method = function(){/*this method is created every time a new object is created */}
    }
    some_object.prototype.some_method = function(){/*this method is created once, but available to all objects of this type*/}
    2 - Some functions which are designed to create new objects, might be useless if called without the "new" keyword, which makes the new keyword seem a bit redundant in those cases.

    One option to get around these is proposed below and I would like feedback and criticism if there's things I've missed or a better way.

    Code:
    function test_function(name)
    {
        // If they didn't use the new keyword, act as if they did.
        if (!(this instanceof test_function)) return new test_function(name);
    
        // Add members to this object's prototype if they haven't already been added.
        var p = test_function.prototype;
        if (p.customised != test_function)
        {
            alert("adding prototype members this one time");
            p.test_method=function(who){alert("name of "+who+" is "+this.name);}
            p.customised=test_function;
        }
        
        this.name = name;
    }
    
    
    var x = new test_function("Ex");
    var y = new test_function("Wy");
    var z = test_function("Zed");
    
    x.test_method("x");
    y.test_method("y");
    z.test_method("z");

  2. #2
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    1. your "missing new" catch-all is not a bad idea, but do know that it does limit later flexibility as coded.

    you can use JS constructors as decorators on existing object via fn.call(), but if you only allow a single class of objects to be returned (test_function), you obviously can't do that without clobbering the prototype.

    ex:
    Code:
    function Person(){
     this.alive=true;
    }
    
    function Man(){
     this.sex="male";
    }
    
    var me =new Person;
    Man.call(me);
    
    console.dir(me) //~ alive: true, sex: "male"


    a better way to guard against a missing new is to allow pass-thrus:


    Code:
    function test_function(name){
        // If they didn't use the new keyword, act as if they did.
        if(Array===this.Array){ return new test_function(name);}

    another issue with your proposal is the concealed prototype methods.
    this has two bad side-effects:
    1. higher RAM usage die to an extra closure (or two w/o new) around all your methods.
    2. unsharable prototype methods; you need an instance to get to the inherited method. this makes debugging harder if your app can't run enough to spawn at least one object, and it prevents auto-complete in the debugger because the method defs are hidden inside a function execution.


    ok, so these are not "end of the world" issues, and you might not care about that sub-set of functionality at all.

  3. #3
    Join Date
    Nov 2010
    Posts
    86
    Thanks for your feedback and sorry for my delay, I only just saw your response as I'd stopped checking for responses after a few days.

    You make good points about the extra ram and the prototype functions being hidden, and I hadn't understood the function.call method until now, so thank you.

    Another aspect to consider is that you might have an application with many different object types, and some are only ever used if a user takes a particular actions. In this case it might save memory if the prototypes aren't defined until at least one of the object-type is used.

    Examples might be popup boxes, message/posting forms, ajax-loaded articles, settings panels, etc. You might have these ready-to-go, so to speak, but not have a lot of object-prototypes defined and in memory, without knowing if any of them will be used.

    If you want a method to be used by multiple prototypes, but not inherit, then you're right that it's more pratical to define it outside the constructor, but in that case you could have a "public function" (i think that's what you call it). Which doesn't belong to any prototype and is just assigned to them as needed, eg.

    Code:
    function dosomething(){this.something = something+1;}
    
    object_type1.prototype.dosomething = dosomething;
    object_type2.prototype.dosomething = dosomething;
    
    ...
    if you want to inherit you can say object_type2.prototype = new object_type1() and this will create object_type1's prototype if it hasn't been created yet.

  4. #4
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    Quote Originally Posted by interfacetricks View Post
    If you want a method to be used by multiple prototypes, but not inherit, then you're right that it's more pratical to define it outside the constructor, but in that case you could have a "public function" (i think that's what you call it). Which doesn't belong to any prototype and is just assigned to them as needed
    There is no public. there's global (top), visible (middle), and local (bottom).

    those unsed protoyotypes could be methods on a tool object, pure functions, named functions, or re-bound object instance methods. regarless, they can all work the same on prototypes as long and the function code uses "this: to read and write changes.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

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



Recent Articles