DEV Community

Discussion on: TIL - Spread and Copying Objects in Javascript

 
pentacular profile image
pentacular • Edited

I'm not complicating it.

Here is a simple piece of code.

let a = 0;
const foo = (v) => { v = 1; }
foo(a);
console.log(a);
  • If foo(a) passes by reference, it will print 1.

  • If foo(a) passes by value it will print 0.

It's as simple as that.

Guess what gets printed in javascript? :)

Now, let's try this with an object to show that it works exactly the same way

let a = { v: 0 };
const foo = (v) => { v = { v: 1 }; }
foo(a);
console.log(JSON.stringify(a));

Guess what gets printed this time? :)

Thread Thread
 
canmingir profile image
Can Mingir

It is passing "Copy of Reference", not the copy of value

What about this?

var a = {};
var b;

function assign(x) {
    b = x;
}

assign(a);

a.test = true;
console.log(b);
Thread Thread
 
pentacular profile image
pentacular

Then it isn't pass-by-reference, is it? :)

Now see if you can find where the ecmascript standard that defines the language refers to object values as references, because I certainly can't.

In your example, you pass the value of a by value to assign and assign it to b.

You can replace assign(a) with b = a;

You then use the value of a to find a property named 'test' and assign it the value true.

You then use the value of b to find the properties associated with that object value and serialize them as JSON.

Note that a === b, so naturally you'll find the same properties when looking up via a or via .

What you may notice is there there's no nonsense about references -- you're just using object values to look up and modify properties.

And that those properties are not part of the value of the object.

Thread Thread
 
canmingir profile image
Can Mingir

There is a reason that the runtime copies reference instead of using original, and still falls in pass-by-reference.

Are you suggesting the runtime makes a copy of a and call function of assign(a)?

Thread Thread
 
pentacular profile image
pentacular

That's exactly what I am explicitly stating.

foo(a) passes a copy of the value of a, regardless of the type of a.

Note that properties are not part of the value of an object, which is where I think you're getting confused.

Thread Thread
 
canmingir profile image
Can Mingir

Again, you are altering terminology in Computer Science; if you are not copying entire a with its properties, it is not pass-by-value.

by copying the value into a new memory region
en.wikipedia.org/wiki/Evaluation_s...

Thread Thread
 
pentacular profile image
pentacular

Sure it is -- those properties aren't part of the object value, and may only be associated by prototypical chaining.

And you may note Scheme in the link you provided -- scheme is pass-by-value but does not copy indirect properties.

Once again, the critical test for pass-by-reference is if changes to the parameter are reflected in the argument.

If it isn't, then it isn't pass-by-reference, and it's clearly in the case in Javascript.

Have you managed to find any mention of 'object reference' in the ecmascript standard yet? :)

Thread Thread
 
canmingir profile image
Can Mingir

Actually, yes, it does:

12.3.6.2 Runtime Semantics: EvaluateCall

  1. If Type(ref) is Reference, then a. If IsPropertyReference(ref) is true, then i. Let thisValue be GetThisValue(ref). b. Else, i. Assert: the base of ref is an Environment Record. ii. Let refEnv be GetBase(ref). iii. Let thisValue be refEnv.WithBaseObject().
  2. Else, a. Let thisValue be undefined.
  3. Let argList be ? ArgumentListEvaluation of arguments.
  4. If Type(func) is not Object, throw a TypeError exception.
  5. If IsCallable(func) is false, throw a TypeError exception.
  6. If tailPosition is true, perform PrepareForTailCall().
  7. Let result be Call(func, thisValue, argList).
  8. Assert: If tailPosition is true, the above call will not return here, but instead evaluation will continue as if the following return has already occurred.
  9. Assert: If result is not an abrupt completion, then Type(result) is an ECMAScript language type.
  10. Return result.

6.2.4 The Reference Specification Type
A Reference is a resolved name or property binding. A Reference consists of three components, the base value
component, the referenced name component, and the Boolean-valued strict reference flag. The base value component
is either undefined, an Object, a Boolean, a String, a Symbol, a Number, a BigInt, or an Environment Record. A base
value component of undefined indicates that the Reference could not be resolved to a binding. The referenced name
component is a String or Symbol value.

Thread Thread
 
pentacular profile image
pentacular

See this bit here?

A Reference is a resolved name or property binding.

Not an object.

An example of using a reference in Javascript is

delete a.b;

where a.b is a reference to a property to be deleted.

I suggest re-reading the section more carefully -- but you are at least on the right track to figuring this out properly. :)

Thread Thread
 
canmingir profile image
Can Mingir

You got so confused "base value" of the the runtime with "primitive value" in ECMA, but my real problem is you are not able to fundamentally distinguish between pass-by-value and pass-by-reference with pure Computer Science terminologies, then I can explain why do they copy references.

Again, it is quite straightforward:

We use the same concept with message brokers in event driven design, which follows same principles.

Thread Thread
 
pentacular profile image
pentacular

Read the algorithm in the ecmascript specification.

Show the part which has a(b) copy a reference. :)

In the process you may come to understand what's happening here and perhaps you'll even come to understand what pass-by-reference means.

Good luck.

Thread Thread
 
canmingir profile image
Can Mingir

12.3.6.2 talking about steps of reference check with different types, and it is super clear.

But I want to back off a bit, can we get at least some consensus on "if you are not sending snapshot of entire object, it is not pass-by-value" theorem, I want to make sure you know what that is, then I promise I'll get you all details one by one.

Thread Thread
 
pentacular profile image
pentacular

"if you are not sending snapshot of entire object, it is not pass-by-value" is obviously wrong.

Now, since it's not obviously wrong to you, let's go over some of the reasons. :)

Pass by value is about the value

So, what is the value?

Let's consider some operations that operate on values.

  1. Can we agree that a = b; assigns the value of b to a?
  2. Can we agree that a === b; compares the value of a and b?
  3. Can we agree that foo(a) passes the value of a to foo?
  4. Can we agree that foo(a) cannot change the value of a?

Please note any of these that you disagree with, and I'll point you at the section of the specification to explain why you're mistaken.

'snapshot of the entire object'

This is fundamentally incoherent -- what are the boundaries of an object?

Is it the reachable sub-graph of values given that object?

(In which case your argument will be that C++ does not support pass-by-value, since it doesn't necessarily copy these or consider them as part of the value)

Is it the immediate properties of the object?

(In which case your argument will be that C++ does not support pass-by-value, since it doesn't necessarily copy these or consider them as part of the value)

Is it something else? Feel free to propose some definition for 'entire snapshot'.

What pass-by-value and pass-by-reference actually mean

So, let's talk about how values work in C++.

C++ supports pass-by-value by requiring the programmer to establish a coherent protocol of copy and comparison operations.

This means that a = b; changes a such that a == b is true. And that given a == b; foo(a); cannot cause a != b to become true without involving side-effects.

This is what pass-by-value means.

C++ also supports pass-by-reference. In these cases foo(a) can cause a != b to become true, because the argument a and the parameter a in foo are effectively the same object.

So, which of these reflects how Javascript works?

If you say it reflects how C++ does pass-by-reference, it's trivial to disprove given the examples I've shown earlier.

Which is presumably why you keep on talking about 'pass-a-copy-of-a-reference'. I hope that it's clear that whatever you're calling it, it isn't pass-by-reference.

If not, I'll be happy to point out why you're mistaken -- just make a claim about the language specification or program behavior.

Good luck.

Thread Thread
 
canmingir profile image
Can Mingir • Edited

Gods of Coffee Mugs say you are so complicating such a simple concept :)

Thread Thread
 
pentacular profile image
pentacular

Let me know if you manage to produce a cogent response to any of the issues I've raised.

Thread Thread
 
canmingir profile image
Can Mingir

Now, since it's not obviously wrong to you

It is obvious to me and at least 791 people on first page.

stackoverflow.com/questions/131044...

Thread Thread
 
pentacular profile image
pentacular

Truth is not a popularity contest.

This is not a cogent response.

Let me know if you come up with one. :)

Thread Thread
 
canmingir profile image
Can Mingir

Let me know if you come up with one

Honestly, I don't know where to begin for someone fails to understand Wikipedia-level concept

Truth is not a popularity contest.

..and it is high school argument