Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

function arguments

function Foo(f) {
   var f = f;    
}

Here inside the function, variable f is local to the Foo (it has a function scope), but why is the variable f in the argument list not in conflict? Maybe because it is bound inside the Foo.arguments object?

In other languages we cannot declare an argument variable with the same name as a local variable.

How is this name ambiguity resolved? Or, How do you reference each of the two distinct f variables later in the method?

like image 652
xdevel2000 Avatar asked Mar 19 '09 15:03

xdevel2000


4 Answers

JavaScript does a couple of things that aren't obviously intuitive - the one you're interested in is called "hoisting" - JS moves var declarations to the top of a function, where they serve the sole purpose of reserving this variable name as a local variable in the function's scope. Sometimes, this leads to lots of weirdness. If the variable name is already reserved as a local variable (e.g. it's an argument) the var declaration gets dropped entirely.

Another unintuitive part of JS is how it deals with argument variables and the arguments object (which are a bit special, as Hippo showed). That's not necessarily what you're interested in, though - what's important for your example is that arguments also declare that variable name as local to the function.

The result of all this is that when you have a var f as well as an argument name f, the `var f' gets dropped, and your example is equivalent to:

function Foo(f) {
   f = f;
}

You can see this in Hippo's example, because:

function foo(f) {
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    var f = 10;
    console.log(f); // --> 10
    console.log(arguments); // --> [10] (!!!)
}

Is equivalent to:

function foo(f) {
    var f;
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    f = 10;
    console.log(f); // --> 10
    console.log(arguments); // --> [10] (!!!)
}

Is equivalent to:

function foo(f) {
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    f = 10;
    console.log(f); // --> 10
    console.log(arguments); // --> [10] (!!!)
}

For more details, read up section 10.1.3 - Variable Instantiation (bottom of p.37) in ECMA-262, the JS specification.

like image 91
Andrey Fedorov Avatar answered Oct 12 '22 23:10

Andrey Fedorov


There is no way to solve this problem, except renaming one of them, or storing the value in another variable.

function foo(f) {
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    var f=10;
    console.log(f); // --> 10
    console.log(arguments); //even this is now array [10]
}
foo(11);
like image 22
TheHippo Avatar answered Oct 13 '22 01:10

TheHippo


Once you declare a new variable with the same name of an old one, it overrides it and you cannot reference both at the same time.

You should either change the parameter or the variable name.

like image 29
Seb Avatar answered Oct 13 '22 01:10

Seb


here inside the function variable f is local to the Foo (it has a function scope) but the variable f in argument list that is named in the same way why it isn't in conflict may be because it is bound inside the Foo.arguments object?

No, it is not bound on arguments: arguments is only an Array of positional argument values, you can't get ‘arguments.f’ out of it.

Arguments passed into a function by name become local variables. The “var f” in a function with argument ‘f’ is implicit.

When you declare ‘var f’ on a variable that is already local, nothing happens. Your code is identical to:

function Foo(f)
{
    f = f;
}

In other languages we cannot declare an argument variable with the same name as a local variable.

In JavaScript, as long as there is one use of “var x” in a scope block, any use of ‘x’ in that block is local. You can happily declare ‘var’ on the same variable in the same scope again and again, but it doesn't do anything.

like image 25
bobince Avatar answered Oct 13 '22 00:10

bobince