1

I'm doing some programming in node these days and I'm kinda surprised by the handling of scope in functions. I was led to believe that now with ES6 scope is a lot stricter. The following works as expected:

function f(v){ v += 1; return v; } let before = 1; let after = f(before); console.log(after); // This logs 2 (as expected) console.log(before); // This logs 1 (as expected) 

But when I do the same using a object/dictionary, the scope of the variable seems to go outside the function:

function f(v){ v.a += 1; return v; } let before = {a: 1}; let after = f(before); console.log(after.a); // This logs 2 (as expected) console.log(before.a); // This also logs 2 (I was expecting this to still be 1) 

Why on earth is this the case? Why is the scope of v limited to the function when it's an int, but not when it's an object?

7
  • This seems like a case of primitive data types vs. objects. A similar thing would happen in Java with ints vs. Strings Commented Mar 15, 2018 at 9:13
  • In JS, only string and number are passed by value, anything else are passed by reference / pointer. It has nothing to do with ES6. Commented Mar 15, 2018 at 9:17
  • @t.niese Something like that. Objects are not copied. But what does get copied, is a reference to those objects. So, before and after are different references, but they have the same value: address of the object itself. Commented Mar 15, 2018 at 9:25
  • 1
    @FisNaN You need to take care if you use the term reference and pointer. Pass by reference does not really exists in js, at least not in the sens that function test(a) { a = {foo:1} } test(b); console.log(b.foo) would work. Commented Mar 15, 2018 at 9:26
  • 1
    @Zlatko Yes I know. But I didn't have the time (or lets to be honest the motivation) to write an answer with the correct terms. :) And as of that it was just a comment. But your answer explains it well. Commented Mar 15, 2018 at 9:30

3 Answers 3

1

There is nothing wrong with scopes here. Your code is simply assigning an object to another variable, so whenever you edit your object, all assigned variables will be affected :

let o1 = { a: 1 }; let o2 = o1; o1.a++; console.log(o2);

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

1 Comment

without an explanation of references vs values this answer is very incomplete
1

JavaScript functions pass all arguments by value.

In the first case, you have a primitive value (number is primitive). So, before refers to a primitive, value 1. You pass it in - it's passed by value. You return a value. Assign it to the second object. after is another object. Basically, two pointers, to different objects. Different objects. Different values.

Think of it in terms of garbage collection. You lose "before" out of your scope. That 1 primitive is no longer accessible. Free to clean up.

In the second case, you pass a value of the object reference. And you return again a value of an object reference. So before and after refer to the SAME OBJECT. They are different references. So, in both console.log(before) and console.log(after), you refer to the same object and the same (now modified) value.

Now, again, look at the garbage collector. Remove access to before. Garbage collector removes it's value (which is, basically, a pointer to the object {v: 2}). Can it remove the object itself? Nope, not yet, because the value of after still points to this object. But regardless of that, both vars point to the same object.

Comments

1

Javascript has two data types: primitive and Object.

In your first example, you're passing in a primitive data type (Boolean, Null, Undefined, String, Symbol, and Number - your case). When you pass these types of variables into a function, you're passing a copy - so anything modified does not affect the initial value/variable, as in your first case.

With the Object data type, when you pass an object into a function, you're passing in a reference to that object's value - not a copy of that value, as with primitives. So when you modify this in your function, you're modifying the reference. This means that any variables that have this reference will have the modified value as well, since they're just pointing to a value that has recently been modified.

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.