views:

73

answers:

3

I'm using a classical javascript prototypal inheritance, like this:

function Foo() {}   
Naknek.prototype = {
//Do something
};
var Foo = window.Foo = new Foo();

I want to know how I can improve this and why I can't use this model:

var Foo = window.Foo = new function() {
};
Foo.prototype = {
//Do something
};

Why this code doesn't work? In my head this is more logical than the classical prototypal inheritance.

+1  A: 

"doesn't work" is vague, but I think the root cause is new function() { (new doesn't belong here)

You probably want:

var Foo = window.Foo = function() {
};
Foo.prototype = {
  bar: 'baz'
};

alert(new Foo().bar); // baz
Matt
+2  A: 

You are using the new operator on the function expression, that causes a newly created object to be assigned to window.Foo.

That new object is not a function, therefore it doesn't have a prototype property and it cannot be invoked.

CMS
+8  A: 

Your var Foo = window.Foo = new Foo(); example is...odd. First you declare a function Foo, then you assign something to its prototype (I assume you meant to replace Nannak with Foo in your second line), and then you overwrite the reference to the function by assigning to it.

Standard Javascript prototypical inheritance looks like this:

// Create a constructor `Foo`
function Foo() {
}

// Give the prototype for `Foo` objects a function bound to the
// property `bar`
Foo.prototype.bar = function() {
}

// Only do this bit if you're doing this within a function and you want
// to make `Foo` available as a property of `window` (e.g., effectively
// a global variable. If this code is already at global scope, there's
// no need to do this.
window.Foo = Foo;

Here's how you'd use Foo:

// Create a `Foo` and use its `bar`
var f = new Foo();
f.bar();

A couple of other notes:

  • Never use new function() { ... } unless you really, really know what you're doing. It creates an object initialized by the function, it does not create a new function. There's almost never any need for the similar (but totally different) new Function(...), either, again except for some advanced edge cases.
  • The function bound to bar in my example above is anonymous (the property it's bound to has a name, but the function does not). I'm not a fan of anonymous functions, but I didn't want to clutter the example above. More here.
  • If you use var at global scope (it wasn't clear from your question whether you were), it creates a property on the window object. You'd only need to do var Foo = window.Foo = ... if you're within a function and want to both create a propety of window and create a local variable called Foo. (Which maybe you meant to do! :-) )
  • The Foo.prototype = { .. }; way of assigning prototypical properties works, but it's not generally a good idea (again, unless you're pretty up-to-speed on this stuff). When you do that, you're completely replacing the prototype object used when you call the function via new, whereas if you just add properties to it (Foo.prototype.bar = ...), you're just augmenting the prototype, not replacing it. Replacing the prototype is perfectly valid, but there are some non-obvious things that can happen if you're unwary. :-)
T.J. Crowder
Now I am wondering: what are those “advanced edge cases”? Are there [legitimate uses of the Function constructor?](http://stackoverflow.com/questions/3026089/legitimate-uses-of-the-function-constructor)
Marcel Korpel
@Marcel: LOL! And the answer is: Of course there are. But you have to know what you're dealing with, and the OP is clearly a newbie (as we are were once), so...
T.J. Crowder