0

I was wondering if anybody out there could help me understand why the name within the function does not relate to the name variable outside of the function. What if you wanted to change the global variable of name within the function, is there anyway to do it?

var name = "Paul";

function test(name){
  name = name || 'You';
  console.log(name);
}

test('Mario');

console.log(name);

Update: Thanks for the quick replies guys. So if you run it line by line is this what's happening?

Once you pass Mario into the function it replaces all the instances of name with the name passed to the function? So in turn you get:

  "Mario" = "Mario" || 'You';

but if you pass nothing:

test();

Then doesn't name = name? why would it take the || statement?

Sean Redmond
  • 3,974
  • 22
  • 28
MarioD
  • 1,703
  • 1
  • 14
  • 24
  • Can't you call your function parameter in a different way? – Claudio Redi Jul 07 '13 at 23:06
  • If that variable is truly global, which hopefully it isn't, you can refer to it using `window.name` (assuming you are in a browser environment). – go-oleg Jul 07 '13 at 23:07
  • @go-oleg: If it were in the global scope, things might get a little interesting: `window.name` is already used for [something else entirely](https://developer.mozilla.org/en-US/docs/Web/API/window.name). – icktoofay Jul 07 '13 at 23:22

5 Answers5

2
var name = "Paul";   

function test(nameInput){
  name = nameInput || 'You';
  console.log(name);
}

The key issue is that you have a local and a global variable with the same name. The local variable will take precedence over the global one. Rename the input variable to be able to reference both.

TGH
  • 38,769
  • 12
  • 102
  • 135
  • I didn't downvote, but I think a little explanation is warranted. – icktoofay Jul 07 '13 at 23:09
  • I agree. Updated with some more text – TGH Jul 07 '13 at 23:10
  • It let's you reference both variables, and illustrates why there is a conflict – TGH Jul 07 '13 at 23:15
  • But you don't need to reference both. The function is basically just returning a given value or a default if parameter isn't there (like Python's `get()`). You only need the parameter. Why limit a function to operating on one global variable? – Sean Redmond Jul 07 '13 at 23:18
  • I agree that there are multiple patterns that can potentially improve this, but I think it's important given this context to show why this doesn't work. That lesson is just as valid as learning new improved patterns. In fact I think it's a necessary first step – TGH Jul 07 '13 at 23:22
  • I'm still a litte it confused because I thought to set a local variable you had to do var name = name and if you left out the var it would cause the global variable to change. (I'm not actually using this code for anything, just using this example to try and get an understanding of what is happening in this situation.) – MarioD Jul 07 '13 at 23:22
  • It's local because it's being defined in the method definition. The var keyword is not used when defining input params to methods – TGH Jul 07 '13 at 23:24
  • 1
    TGH, thank you! that's exactly what I was looking for. I know it was a newb question but it really confused me. Thanks to everyone else as well, some great points in here! – MarioD Jul 07 '13 at 23:27
1

You have a global variable called name and a function parameter called name. When you call test, the name parameter becomes a local variable, shadowing the global variable. If you want to access the global variable, you'll have to change one of the variable names so the local variable/parameter doesn't shadow the global variable.

icktoofay
  • 126,289
  • 21
  • 250
  • 231
0

There is a problem - argument main clears visibility of the global name variable (shadows). So you should rename the argument to access the global one.

sasha.sochka
  • 14,395
  • 10
  • 44
  • 68
0

The change to name in the function is local to the function. If you want to change the global variable you'll need to return the changed name from the function.

function test(name){
  name = name || 'You';
  console.log(name);
  return name;
}

name = test('Mario');

For everyone who's saying to use a different name for the parameter, that does't address all the problems you can run into if you're confused about scope and mix global and local variables.

It seems the OP wants a function that works like the Python dict get() method. If you get the scope worked out the function can work generally for any value. If you just change the name of the parameter, you have a function that only works on one global variable.

Sean Redmond
  • 3,974
  • 22
  • 28
  • 1
    I'm not so sure they are confused about scope; you could indeed change it to return a value rather than changing a global variable's value, but there are cases where you *would* want a function to change a global variable's value. What if the function's name was `changeName`, say? One might be able to argue that it's bad design to do it that way, but that's not what the question is about. – icktoofay Jul 07 '13 at 23:21
  • Why not kill two birds with one stone? The problem in the question is about scope and understanding scope should lead to better design. So let's not make suggestions that lead to bad design :-) – Sean Redmond Jul 07 '13 at 23:27
  • Hey guys, thanks for taking the time to answer my question. This was just an example that really confused me, and I know the naming was horrible, but I really wanted to know what was happening behind the scenes that caused it to not act as if you were simply setting another global var from within the function. – MarioD Jul 07 '13 at 23:31
  • No problem. Check [this answer](http://stackoverflow.com/a/500459/131226) for a good rundown of scope situations. – Sean Redmond Jul 07 '13 at 23:36
0

The variable "name" is being redefined in the local scope of the function, in your example.

In order for this to work in the way you desire, you must name the local variable something different so that you can set the global variable to another value.

Here's a sample:

var name = "Paul";

function test(newName){
    name = newName;
    console.log(name); // is now Mario
}

test('Mario');

console.log(name); // reads Mario from the global variable
jrthib
  • 1,319
  • 1
  • 12
  • 17