Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A closure name clashes with function of same name inside it, but only in Chrome

Would this be considered a Chrome bug or a Safari/Firefox leniency?

When I create a closure function, I give it an arbitrary name, "Button". Within the closure, I have a function which is a constructor for the main object the closure creates, also called "Button".

The closure returns a reference to Button, presumably the inner function Button().

var closure = (function Button(){

    //the closure's primary object
    function Button(target) {
        //constructor for our button object
    }

    Button.prototype = e.inherit(e.Plugin.prototype);
    Button.prototype.constructor = Button;

    return {
            Button: Button,
        };

}());

//now let's call our closure to create a new Button
var newButton = new closure.Button()

In Safari and Firefox, this is not a problem. Calling new closure.Button() returns an instance of the inner Button(). In Chrome, however, when an inner function name matches the closure function name, the constructor appears NOT to be called. What is returned seems to be the closure function itself. This, of course, leads to errors when the inner function defines methods that I later try and call.

I'm posting this question for two reasons:

1) It took me more than a day to find the cause of the problem, which was Chrome reporting that my Button does not have method .activate (in my real code, the Button inherits from a parent object that provides an .activate() method). If anyone else runs into this issue, then they may find my question here and save themselves some time.

2) I'm wondering: if this is an error on my part, to use the same name for both the closure and a function within the closure, why is it working in Safari/Firefox? More specifically, is Chrome indeed somehow making the closure return itself and not the intended inner function? Is this a bug?

like image 696
Zac Imboden Avatar asked Nov 13 '22 16:11

Zac Imboden


1 Answers

Probably not the exact problem, but you unnecessarily named the function expression.

var closure = (function Button(){

    //the closure's primary object
    function Button(target) {
        //constructor for our button object
    }

    Button.prototype = e.inherit(e.Plugin.prototype);
    Button.prototype.constructor = Button;

    return {
            Button: Button,
        };

}());
//now let's call our closure to create a new Button
var newButton = new closure.Button()

Should be

var closure = (function (){

    //the closure's primary object
    function Button(target) {
        //constructor for our button object
    }

    Button.prototype = e.inherit(e.Plugin.prototype);
    Button.prototype.constructor = Button;

    return {
            Button: Button
        };

}());

//now let's call our closure to create a new Button
var newButton = new closure.Button();

The difference being that the top level function is unnamed. No need to name something you will never use again.

Also, you should not have a comma within the return object. This should come up as a syntax error.

Also, you have no closing semi colon on the last line.

like image 154
dqhendricks Avatar answered Nov 15 '22 04:11

dqhendricks