22

I've realized you can have a property in an object run automatically like this:

var obj = {

    init:(function(){ alert('loaded');})();

}

I'm trying to use this method as an initializer for the object. The problem I'm running into is passing a reference to 'obj' to the init property. I suspect it generates errors because the obj hasn't been completely built in browser yet. I'm trying to do the following, but unsuccessfully. If there's a way to do this, I'd love to know how.

var obj = {
    prop:function(){ alert('This just ran.'); },
    init:(function(){ obj.prop(); })();
}

9 Answers 9

23

If you want to create multiple instances of similar objects, you should use plain old constructor functions (remember to put shared properties in the prototype!).

If you want to create a single object, consider using an anonymous constructor. Your example would read:

var obj = new (function() {
    this.prop = function() {
        alert('This just ran.');
    }

    // init code goes here:
    this.prop();
});

This has an additional benefit over object literals: the constructor function can be used as a closure over 'private' variables.

Don't overuse object literals: they may make simple things simple, but complex things will get overly complicated.

Sign up to request clarification or add additional context in comments.

2 Comments

Interesting. Do you know where I can find documentation on these anonymous constructors?
@JW, I believe an anonymous constructor is just an anonymous function being used as a constructor (i.e. called with the new keyword). See also stackoverflow.com/questions/20057431/… and enfinery.com/30/javascript-the-case-of-an-anonymous-constructor
5

This is not possible: obj doesn't exist until the whole block is interpreted.

Comments

4

A simple alternative:

var obj = {

  init: function(){ 
    alert('loaded');
  }

}.init();

1 Comment

Noting that this sets obj to whatever value init() returns - which in this example is undefined.
3

Why don't you use the contructor model (actually, I have no idea of its correct name):

function Obj() {
    // Initialising code goes here:
    alert( 'Loaded!' );

    // ...

    // Private properties/methods:
    var message = 'hello',
        sayHello = function() {
            alert(message);
        };

    // Public properties/methods:
    this.prop = function() {
        sayHello();
    };

    // Encapsulation:
    this.setMessage = function(newMessage) {
        message = newMessage;
    };
}

Usage:

var instance = new Obj();
instance.setMessage('Boo');
instance.prop();

1 Comment

A reason for not initialising in the constructor is that you need to call the constructor every time you want a prototype (eg. to make a subclass) — function XObj() {...}; XObj.prototype= new Obj();. You don't really want to initialise an actual instance in this case.
2

Yes, obj does not seem to exist locally till later. This worked for me with setTimeout. Tested ok on IE8, FF5, Chrome 12, Opera v11.5. Not sure about the 50 milliseconds though, I imagine it is enough.

var obj = {
    prop: function() { alert('This just ran.') },
    init: ( function(){ setTimeout(function(){obj.prop()},50) } )()
}

1 Comment

This won't work if the next line after the var statement needs to use obj.prop.
1

this is an update to the example submitted by user1575313.

the original code works but it limits the use of the object after setup. By returning the object reference in the init method it allows the object to be used outside the object.

link to jsFiddle. jsFiddle

var obj = {

init: function()
{ 
    alert('loaded'); 

    this.consoleLog(); 

    /* we want to return this to keep object 
    usable after auto init */ 
    return this;
}, 

consoleLog: function() 
{
    console.log(1); 
}

}.init(); 

/* the obj should now be usable outside the auto init */ 
obj.consoleLog();

Comments

1

Init in jQuery-like style

(function() {

var $ = function(){
  return new $.fn.init();
};

$.fn = $.prototype = {
  init: function(){ 
    this.prop(); 
  },
  i: 0,
  prop: function(){ 
    alert('This just ran. Count: ' + (++this.i)); 
    return this;
  }
};

$.fn.init.prototype = $.fn;

$().prop().prop();

})();

jsbin.com

Comments

0

I think you want to try something like this:

var obj = {
    prop: function() { alert('This just ran.'); },
    init: function() { obj.prop(); }
}

Object literals reqire comma-separated members without semicolons.

2 Comments

that wont run the init function on creation though
You are right - there isn't any way to do that with object literals.
-1

Does it work if you pass "this" into the init function?

something like: (untested)

var obj = {
    prop:function(){ alert('This just ran.'); },
    init:(function(o){ o.prop(); })(this);
}

2 Comments

Nah. Passing (this) is a reference to window.object
Not directly related, but you can quickly prototype and test stuff using jsfiddle.net

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.