5

Can anyone explain the difference in behaviour between Internet Explorer and Firefox in regards to the below:

var myNamespace = (function () {
  var exposed = {};

  exposed.myFunction = function myFunction () {
    return "Works!";
  }

  console.log(myFunction()); 
  // IE: "Works!"
  // Firefox: ReferenceError: myFunction is not defined

  console.log(exposed.myFunction());
  // IE: "Works!"
  // FF: "Works!"

  return exposed;
})();

console.log(myNamespace.myFunction()); 
// IE: "Works!"
// FF: "Works!"

In internet explorer this method allows me to call my function from inside my namespace function by using either myFunction() or exposed.myFunction().

Outside my namepsace function I can use myNamespace.myFunction()

In Firefox, the results are the same with the exception of the bare named function call which does not work.

Should it work? If it shouldn't, then why not?

If it should then is this a known bug?

4

3 Answers 3

6

To prevent false information:

IE has a problem with named function expressions which is what you have. The name of the function should only be available inside the function. From the specification:

The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.

where FunctionExpression is defined as:

FunctionExpression :
     function Identifieropt ( FormalParameterListopt ) { FunctionBody }

But in IE, instead of making the name only available inside the function, it creates two different function objects, one assigned to the variable and the other to the name you gave the function. The following will yield false in IE (and throw an error in other browsers):

exposed.myFunction === myFunction;

It's a known bug and if you have to code for (older versions of) IE, you better avoid named function expressions.


Related question:

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

5 Comments

Brilliant! This explain perfectly why the code above 'works' in IE and not in Firefox. Of course, the behaviour in Firefox is not what I epxected but it is on spec, which is what matters.
console.log(myFunction());, working for IE, is a call to the local function that according to your specifications, should exist. (FunctionBody, in this context, is the nearest enveloppe of exposed, exactly where the bare call is made)
@Sebas: No, we are talking about the FunctionExpression's FunctionBody, not the FunctionBody it is defined in. Maybe you haven't seen my update yet. According to the specification, it should not exist.
I understand your point. Maybe I'm interpreting it wrongly, but to me there's a problem here because we're talking about declaring functions and their related scope (in which I agree 100% with your post) when actually there's an overlaying function affectation. See my post: the declaration of the function is definitely outside of the body of exposed, even though afterwards, it is affected to it as a property. But maybe I'm misunderstanding the engine.
@Sebas: To be honest, I cannot follow your last comment. The problem at hand is that IE creates a symbol with the name of the function expression in the scope where the function is defined, and this is wrong. Everything else is irrelevant.
2

This:

exposed.myFunction = function myFunction () {
    return "Works!";
}

is useless (- correcting myself: it is NOT incorrect - ) and apparently buggy (see Felix's post). If you wish to declare a function part of exposed you don't need to name it:

exposed.myFunction = function() {
    return "Works!";
}

However, if you want to declare a local function and then also affect it to your array exposed, you can do:

function myFunction () {
    return "Works!";
}

exposed.myFunction = myFunction;

which would, in this case, successfully validate (exposed.myFunction === myFunction) === true;

Also, please note that your call to console.log(myNamespace.myFunction()); is identical to your call to console.log(exposed.myFunction()); since myNamespace is actually the object exposed.

5 Comments

It is NOT incorrect. It's a named function expression and perfectly valid JavaScript.
then firefox should allow the execution of the console.log(myFunction());, otherwise there's an inconsistency.
No, IE should properly implement JavaScript.
I mean, if you say the first expression is correct, then it means the declaration of the bare myFunction should be taken in consideration as of the current context, hence be valid called as is.
But that's not how function expressions are defined. See my answer.
0

Also, By defining

exposed.myFunction = function() {}

You are setting exposed's property to be myFunction.

And it is not available in the myNamespace scope.

By defining

exposed.myFunction = function myFunction() {}

The function is created in the scope of myNamespace, and then referenced as a property of exposed.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.