tags:

views:

203

answers:

4

If We have

var randomname = {};
randomname.attribute = 'something';

function randomname(){
  alert(randomname.attribute);
}
randomname();

Will javascript throw any errors?


Update
So, We know that we cannot have a object have the same name as a function.

Why is this?

Should javascript not be able to tell what you are after by the way you call it?

+3  A: 

Your function randomname() is redefining the randomname identifier, thus losing your reference to the object you constructed earlier. It may look more clear like this:

var randomname = {};
randomname.attribute = 'something';

var randomname = function () {
  alert(randomname.attribute);
};

randomname();

It is like doing:

var a = 5;
var a = [20, 30];

console.log(a);  // returns [20, 30]
Daniel Vassallo
When using `function randomname () {}` as opposed to `var randomname = function () {}` there is different behavior. The former throws a TypeError, whereas the latter works correctly -- alerting with undefined. I do not think they are equivalent. Tried it in the WebKit console. EDIT: No errors are thrown in FF. Must be a WebKit console bug.
CD Sanchez
@Daniel: Checking in Chrome console, you're right. The example of the OP returns `Type Error`. Does not happen in Firebug. Looks like a WebKit bug to me too.
Daniel Vassallo
@Daniel Vassallo: I know the difference, but Chrome is throwing an error when not using variable assignment for the function definition. This is what I'm trying: http://pastebin.com/KzXQjLny
CD Sanchez
@Daniel: Yes, sorry. Deleted my comment after I found out that it's true :) I was only checking the second example (the one in my answer).
Daniel Vassallo
I tried it on http://jsfiddle.net/5vHtg/ and I still get the error, so it's not limited to the console. Odd.
CD Sanchez
@Daniel: Yes, very strange! ... There's definitely something different happening in Chrome and Safari when using a function statement.
Daniel Vassallo
Anyone going to submit this as a bug to webkit?
Hailwood
I'm trying to understand if it is intentional... AFAIK Safari and Chrome use different JavaScript engines, and both are handling it in the same way.
Daniel Vassallo
If you have node.js (which uses v8, or chrome's JS engine) you could try running the code there. If it doesn't produce an error, then it's most likely related to WebKit.
CD Sanchez
Webkit is showing the "right" behavior, the function declaration makes the `randomname` identifier available when entering the execution context, later the assignment `randomname = {};` is made, Firebug is the one who has problems.
CMS
That makes sense. Thank you @CMS.
CD Sanchez
@Daniel: Thanks, I've posted [an answer](http://stackoverflow.com/questions/3663775/object-name-same-a-function-name/3664199#3664199), I explain why Firefox behaves differently.
CMS
+2  A: 
function randomname(){
  alert(randomname.attribute);
}

is roughly the same as this:

var randomname = function() {
  alert(randomname.attribute);
}

It's not 100% identical, since with the first syntax you can refer to functions "in the future", but this is basically how it works. There is only once namespace for functions and variables, since functions get assigned to variables.

Douglas
+1... I think the "functions in the future" thing is called *hoisting* :)
Daniel Vassallo
thanks about the "hoisting" and "future function" I did not about this until now
Eugene Ramirez
Oddly, in Chrome the two do not seem to be equivalent. The first example will throw a `TypeError`. I believe what you posted is the correct behavior, but just a heads up so someone doesn't get bitten by this "bug."
CD Sanchez
A: 

forgive my pedant reply. your question is a bit confusing, or is this a tricky question. In the second line you wrote

var randomname.attribute....

if thats your point, then it is an illegal statement and will definitely throw an exception. But if your point is about the fourth line where you reused the same name.

note that you wrote

function randomname(){...}

instead of

var randomname  = function(){...}

I dont know why, but because you used a future function, you wont be able to override preexisting names. therefore randomname will still be a hash instead of a function, thus throwing an exception.

My question is, so what will happen to randomname function? How can we call it? Is it a wasted resource? As a general rule I always use

var randomname = function{..}

template so I am always assured that name conflicts wont happen so I never encounter this.

Eugene Ramirez
+6  A: 

It should give you a TypeError exception -for trying to invoke an object-, the behavior observed in the Firebug's console is not right...

FunctionDeclaration's are hoisted to the top of their enclosing scope, your code is actually executing in this order:

// FunctionDeclaration is hoisted
function randomname(){
  alert(randomname.attribute);
}

// the var has no observable effect, because
// the randonmane identifier is already defined
randomname = {};
randomname.attribute = 'something';

randomname(); // TypeError, randomname is not callable.

When entering to an execution context, the Variable Instantiation process (aka Declaration Binding Instantiation in ES5) defines the properties on the Activation Object (AO, this is a non-reachable object that holds identifiers of variables, functions declarations and function arguments in the local scope) in the following order:

  1. FormalParameterList identifiers (for Function Code)
  2. FunctionDeclaration identifiers
  3. VariableDeclaration identifiers

A VariableDeclaration will not overwrite an identifier has been already defined in the AO (e.g. by one of the first two steps), but the assignment will do it at run time.

For example:

(function (foo) {
  var foo; // doesn't affect the existing `foo` identifier
  return typeof foo;
  function foo () {}
})('string'); // yields "function"

But if an assignment is made, the value of the identifier will be replaced, for example:

(function (foo) {
  var foo = {};
  return typeof foo;
  function foo () {}
})('string'); // yields "object"!!

In the above example, when the function is invoked, -but before the code execution- the foo identifier is set up on the Activation Object (aka Variable Object).

First it gets assigned the value of the formal parameter, the value 'string', then all FunctionDeclaration's on the Function Body are examined, a function named foo is found, then the foo identifier will point to that function.

After that, all Variable Declarations are examined, we have one with the identifier foo, but its value is respected in this time -remember that the function hasn't been executed-.

At this point, the function is ready to be executed, its lexical and variable environment is setup.

The first thing that will be executed in the function, is the assignment foo = {};, which replaces the reference to the function that we had before.

Why it behaves differently on other browsers and Firefox?

Because:

  1. The Firebug's console wraps your code before evaluating it.
  2. The Mozilla implementations define a Function Statement

Since Firebug evaluates code by wrapping inside a with statement, this causes the FunctionDeclaration to be evaluated in statement context -a Mozilla's Function Statement-.

To show the behavior of the Function statement on Mozilla implementations, consider the following example:

if (true) {
  function foo () { return 'true!';}
} else {
  function foo () { return 'false??!';}
}

foo();

In Mozilla you will get 'true!', while in other implementations you will get 'false??!' - even on IE-.

That's because the function definition was made at run-time, in Statement context (in side the true branch of the if), while in other implementations, the function declarations are evaluated at parse time.

The above example should actually produce a SyntaxError exception on any implementation, but that doesn't happen on any of them...

A FunctionDeclaration should be allowed only, in global code or directly in the FunctionBody of a function.

A lot of people use interchangeably the terms Function Declaration and Function Statement but that's totally wrong, ECMAScript doesn't define a Function Statement, is a non-standard feature.

The specification has a brief note on this issue:

NOTE: Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement. However there are significant and irreconcilable variations among the implementations in the semantics applied to such FunctionDeclarations. Because of these irreconcilable difference, the use of a FunctionDeclaration as a Statement results in code that is not reliably portable among implementations. It is recommended that ECMAScript implementations either disallow this usage of FunctionDeclaration or issue a warning when such a usage is encountered. Future editions of ECMAScript may define alternative portable means for declaring functions in a Statement context.

Try to run your code in the global execution context -in a simple <script> element- and you will see it crash also on Firefox:

<script type="text/javascript"> 
  var randomname = {};
  randomname.attribute = 'something';

  function randomname(){
    alert(randomname.attribute);
  }
  randomname();
</script>

You can find the above example here, make sure to open the Firebug's console and you'll see the same error you get on other browsers.

CMS
All hail arcane implementation details. And I thought I knew stuff about Javascript. Though once again I think the official spec gets it wrong and do not intend to stop using Function Statements within other functions so long as it does not seem to cause issues (and so far I have not seen any).
MooGoo