3

I have been watching a video series by Douglas Crockford. I am a little confused on the relationship of assigning variables as a parameter of assigning variables as a global variable, let me demonstrate.

var bob = 22; //global scope
function funky(parameter){
    parameter = null; //sets the var passed in to null
    bob = 44; //sets the bob 
}

var hello = [];
funky(hello); // hello still has the value of an empty array even after the function is invoked.
bob; // value is 44

So 'var bob' is assigned 44 when funky() is invoked. This bob holds the new value outside the scope of the function.

var hello is passed as a parameter, while inside funky, it has the value null, outside when hello is invoked in global space, it holds the value of an empty array.

Is this just something I have to memorize? If a defined variable in global scope is passed as a parameter, it will only hold it's new assigned value within the scope of the function? Am I missing something at a broader scope with either how a parameter is passed and assigned in a function?

Here is a repl.it of the code with console.log outputs while inside and outside the function/global scope.

http://repl.it/NgN

HelloWorld
  • 10,529
  • 10
  • 31
  • 50
  • 2
    For a moment, think how else would you want this to work? The more you try to answer that question, you will realize that this is how it should work and then you will understand the pattern and you don't have to memorize any more! – Kiran Jan 14 '14 at 19:39
  • 1
    Also, globals are bad. Avoid them! – m59 Jan 14 '14 at 19:39
  • Others will correct me if I'm wrong, but technically, `bob` isn't a global, in that it's not added to the global object (typically `window`). It's simply a non-local variable. When `funky` refers to `bob`, JavaScript creates a [closure](http://en.wikipedia.org/wiki/Closure_(computer_programming)) that allows the function to access the variable. – Scott Mermelstein Jan 14 '14 at 19:54

4 Answers4

3

Because this line

parameter = null;

Only sets the value of the function's parameter, not the value of the variable that was passed in. However, bob inside the function is interpretted as a reference to the global variable, so it does modify the external value.

Note, however, that objects are references, so if you wrote it like this:

function funky(parameter){
    parameter.hello = null;
}

Then calling funky does directly modify the object that the parameter references.

var x = { hello: [] };
funky(x); // x => { hello: null }

Is this just something I have to memorize?

Yes, understanding how parameters are passed is pretty important.

If a defined variable in global scope is passed as a parameter, it will only hold it's new assigned value within the scope of the function?

Parameters only hold their values within the scope of the function. Global variables are, well, global, so if they are modified inside the function, they keep that value outside the function.

Also, be aware of hiding—if a parameter has the same name as a global variable, the parameter hides the variable within the scope of that function.

p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
1

Regarding this:

var hello is passed as a parameter, while inside funky, it has the value null, outside when hello is invoked in global space, it holds the value of an empty array.

Do not think of parameter as an alias for hello. They are distinct variables. They are free to point to different things. Assigning a value -- null in this case -- to parameter has no effect on hello. After that line, the global variable hello still points to an empty array. Only parameter points to null.

Furthermore, funky(hello) passes the value of hello to the funky function. Consider the following:

var arr = [];

function addElements(arr) {
    arr.push(5);
    arr.push(77);
}

The global arr is still empty after addElements executes. The arr inside the function is distinct from the arr in the global scope. (I should note that the contents of each arr may point to the same objects, but that's a separate issue.)

(Note also that some languages do allow the sort of aliasing you seem to expect, but that's not how parameters are passed in JavaScript.)

Wayne
  • 59,728
  • 15
  • 131
  • 126
1

JavaScript assumes that if you assign a value to a variable it is in the global scope—unless that variable is declared with a var. Like for example, this:

var bob = 22; //global scope
function funky(parameter){
    parameter = null; //sets the var passed in to null
    var bob = 44; //sets the bob 
}
var hello = [];
funky(hello); // hello still has the value of an empty array even after the function is invoked.
bob; // value is 22

Since the function's bob variable is declared with a var, it is owned by the local scope of the function and has no impact on the bob declared outside the function's scope.

Regarding how objects differ from primitives when passed into functions, check out Jonathan Snook's article http://snook.ca/archives/javascript/javascript_pass and the helpful comment from @p.s.w.g.

Harvey A. Ramer
  • 763
  • 7
  • 13
  • 1
    Thank you @Codey. You are asking the right questions. I think someone else recommended Douglas Crockford's book, JavaScript: The Good Parts, and I concur. Buy the paper version if you don't have it yet. – Harvey A. Ramer Jan 14 '14 at 20:22
1

ok, so the following example will confuse you even more.

var a = {'a': 'A'};

function foo(param){param.a = 'B';}

foo(a);

// now print a {'a': 'B'}

Here's an important concept:

Primitives are passed by value, Objects are passed by "copy of a reference".

As for more information, you can check this answer: Does Javascript pass by reference?

Community
  • 1
  • 1
Yang
  • 86
  • 1
  • 8
  • Haha, this does confuse me more, but this is something I don't have a great understanding of. Thanks for pointing this out @yang – HelloWorld Jan 14 '14 at 20:08