News for hackers. Stuff that matters.
Re:Deep-copying in JavaScript by kevincennis on Thursday January 25, 2018 @02:30PM (#16233785)
JavaScript is absolutely not pass by reference.

    let a = 1;
    
    function foo( a ) {
      a = 2;
    }
    
    foo( a );
    
    console.log( a ); // 1
Re:Deep-copying in JavaScript by andrewstuart2 on Thursday January 25, 2018 @05:03PM (#16235120)
"By reference" means different things to different people.

The most accurate statement I've found is that JavaScript, much like Java, passes reference-by-value. Everything is passed by value, but if your value is an object, then the new scope gets a copy of the reference. If you modify the object by dereferencing (that is, `a.foo = "bar";`), your modifications to the object persist outside of your scope.

This is an important understanding to have when working with JavaScript.

Re:Deep-copying in JavaScript by pjmlp on Thursday January 25, 2018 @05:18PM (#16235241)
Everything is passed by value.

A numeric value is put into the call stack.

Which in the case of references happens to be the address of pointee.

It is only pass by reference, if what is put into the call stack is the address of the actual variable on the caller stack holding the data.

Re:Deep-copying in JavaScript by andrewstuart2 on Thursday January 25, 2018 @05:22PM (#16235267)
Isn't that what I said? That's what I was trying to say, at least, but keeping the language more js-oriented.
Re:Deep-copying in JavaScript by ZeroBugBounce on Thursday January 25, 2018 @06:31PM (#16235761)
I'm not the parent commenter but yes, you both made the same distinction as far as I can tell.
Re:Deep-copying in JavaScript by Stratoscope on Thursday January 25, 2018 @07:23PM (#16236059)
It doesn't help us understand the language if we try to shoehorn JavaScript's behavior into one of two buckets: "pass by value" or "pass by reference."

As you mentioned elsewhere, these terms are well defined in computer science. But how JavaScript works doesn't match either of them.

It only creates confusion to force JavaScript assignment and parameter passing into one of those two categories. This is what has led to the widespread misconception that "primitives are passed by value, and objects are passed by reference."

We're not implementing JavaScript engines here, we're programming in JavaScript. Implementation details like addresses and pointers are unknown to our code. They may differ from one JavaScript engine to another, and even during a single run of your program as the engine decides on the fly how to optimize or de-optimize your code.

What matters is the observable behavior from the point of view of the running JavaScript code.

There are a few ways you could describe that behavior, such as my notion of a new "name" that refers to an existing "thing", or shkkmo's and andrewstuart2's "pass a reference by value". But it's not "pass by value" as that term is understood in other programming languages such as C/C++.

Re:Deep-copying in JavaScript by pjmlp on Friday January 26, 2018 @03:23AM (#16237722)
No, JavaScript only does pass by value, nothing else.

There is nothing to discuss here other than JavaScript developers trying to imagine stuff instead of learning the underlying literature concepts.

JavaScript is not a special snowflake language.

Computer Science describes how things are supposed to be, they don't change because of language X or Y.

Re:Deep-copying in JavaScript by BeeOnRope on Thursday January 25, 2018 @08:50PM (#16236444)
It's essentially exactly analogous to pass-by-value in C, where references are replaced by pointers. The primary difference is that JavaScript (and many other langues) use references as the only way to refer to an object, whereas C also has the concept of directly referring to an object by value where assignment or passing as a parameter will make a copy of the object.
Re:Deep-copying in JavaScript by k2xl on Thursday January 25, 2018 @05:33PM (#16235344)
It isn't "if the value is an object then scope gets a copy of the reference" No new objects are created when you pass an object.

An object's value is a memory location. When you pass it as an argument you're passing that value into the method. The analogy is more akin to casting than copying.

Re:Deep-copying in JavaScript by jerf on Thursday January 25, 2018 @02:45PM (#16233927)
Nowadays, everything is pass-by-value. The only question is whether a reference or a pointer is one of the things that can be passed by value, or if everything passed is always a copy.

An exception to pass-by-value would be Forth; in the case of stack-based languages there really isn't a "pass" going on at all. But everything copies something for every non-inlined function call nowadays. Another instance where it's less obvious what is going on is a truly immutable language like Erlang or Haskell, where the "value" is quite likely still being passed via a pointer, but that's only relevant from the point of view of considering garbage collection behavior.

This makes the old "pass-by-value vs pass-by-reference" terminology vestigial to the modern software engineer, which is why the only place you'll encounter it is in school courses. A better way of understanding the modern issues is to ask what powers a passed-in value has and just ignore the old question.

Re:Deep-copying in JavaScript by kmill on Thursday January 25, 2018 @03:28PM (#16234320)
Off the top of my head, here are languages in use that have a feature for pass-by-reference semantics: C#, Ada, C++ (though in this language you can get ahold of the reference as a value if you want).

Of course, to implement pass by reference, you tend to have to pass pointers around, but the point is that the language gives the illusion that the identifiers within a function's scope are locations specified by the caller.

I guess a takeaway is that in designing a language, one has to consider the relationship between an identifier, the mutable cell associated with the identifier, and the value stored in that cell. It seem that in common languages the identifier refers to the cell, but if the identifier is used in a value context, it evaluates to the value in the cell. Languages with pass-by-reference semantics let you make your own & function, so to speak.

(A weird example in C of this relationship is that an identifier for an array refers to a cell that contains the whole array, but, if you use the identifier in a value context, it becomes a pointer to the first element. One aspect of it not actually being a pointer is that you cannot replace its value with the pointer to another array.)

Anyway, an everything-must-be-a-first-class-object hard-liner would insist that pass-by-reference is the way of the past. But, sometimes it is not economical to get everything to be a first-class object. For instance, you might decide it is not worth trying to create a pointer type for referring to members of a packed struct, but it is not too hard to make a pass-by-reference feature for this (via copying).

Re:Deep-copying in JavaScript by Roboprog on Thursday January 25, 2018 @05:02PM (#16235109)
Pascal “var” parameters. Pascal is rarely used any more, but I suppose it’s no more obscure than Ada.
Re:Deep-copying in JavaScript by geoelectric on Thursday January 25, 2018 @04:21PM (#16234782)
The key feature of pass-by-reference is whether the callee can replace the value bound to the caller's argument (not mutate it).

In other words, pseudocoded:

    x=1
    changeMe(x)
    write(x) // 2
With that in mind, it's clearer that JS is pass-by-value with object reference values (or pass-by-sharing, though I never hear that in practice) as the caller remains bound to the passed object, but a C++ reference argument is an actual pass-by-reference of the original binding. So's an argument passed to a Pascal/Delphi out or variable parameter, and I'm sure other examples exist as well.

So I guess it depends on what you mean by "nowadays" but I'd still consider C++ a modern language within "everything".

Re:Deep-copying in JavaScript by quicknir on Friday January 26, 2018 @11:50AM (#16240638)
You can never actually replace what the reference is bound to in C++, you can only call the assignment operator. The real distinction here is that in languages like Java and python, assignment is fundamentally different from mutation. In C++ there is no distinction, assignment is just a form of mutation.
Re:Deep-copying in JavaScript by amptorn on Thursday January 25, 2018 @03:04PM (#16234081)
Did you know? Perl is pass-by-reference.

    sub mutate {
      $_[0] = "blue";
    }
    
    my $color = "red";
    mutate($color);
    print($color); # "blue"
Re:Deep-copying in JavaScript by dragonwriter on Thursday January 25, 2018 @04:30PM (#16234859)
> Nowadays, everything is pass-by-value.

Even viewing sharing as a subtype of value, that's not true; call by need exists in modern languages (e.g., Haskell), and, in fact, classic call-by-reference is available in lots of languages, though not the exclusive model in any (and not the primary model in any current popular language I can think of.)

Re:Deep-copying in JavaScript by paulddraper on Thursday January 25, 2018 @03:40PM (#16234438)
> Nowadays, everything is pass-by-value.

Except for obscure, seldom-used languages like C++ and C#.

If you can write

    int a;
    ParseInt("123", a);
    Print(a); // print 123
your language has pass by reference.
Re:Deep-copying in JavaScript by pjmlp on Thursday January 25, 2018 @03:46PM (#16234495)
I would add other unknown languages like Ada, D, VB.NET, Delphi, FreePascal, Rust.
Re:Deep-copying in JavaScript by tomjakubowski on Thursday January 25, 2018 @05:59PM (#16235543)
Rust's references are ordinary values. Moreover, the GP's example wouldn't work in Rust; you'd need to pass a value of type &mut i32 to ParseInt to mutate the value.
Re:Deep-copying in JavaScript by shkkmo on Thursday January 25, 2018 @02:54PM (#16234013)
What are you talking about?

PHP has pass-by-reference: http://php.net/manual/en/language.references.pass.php

Re:Deep-copying in JavaScript by jerf on Thursday January 25, 2018 @02:57PM (#16234032)
And the references are passed by value. There are two places you can find in RAM that will contain that reference, which once you penetrate through the abstractions and wrappers, will be a pointer; that second location is the reference that was passed by value. A reference is basically a pointer that the language prevents you from doing pointer arithmetic on, and in many languages such as PHP, is simply automatically dereferenced for you.

The reason why I brought up languages like Forth is that there really did used to be languages that did not actually "pass" things by value. Forth had a true pass-by-reference, in which there is no second copy of anything, neither the value, nor a pointer to the value. Now it's a dead distinction, in the sense that pass-by-value and pass-by-reference used to be distinguishing, because everything is copying something. Which is why the distinction is sort of confusing to try to apply to modern languages, and produces lots of heat but no light; it's dead, inapplicable to the modern language landscape.

The proper question to be asking is what permissions/privileges are passed by a function's parameter, whether you're allowed to modify it and have the modifications visible to the caller, whether you're not allowed to modify it at all (immutable languages, for instance), or whether there's an entire ownership system around what the passed-in value represents (Rust), not whether or not something was copied when the function call was made. Trying to answer this question in terms of "pass-by-X" doesn't help, if for no other reason than pass-by-X implies there's only two possibilities, and I outlined three classes of possibilities above, each of which can have their own further nuances. Is Rust pass-by-reference or pass-by-value? Well, the question is invalid, in either the original or the modern mutation of the meaning.

Re:Deep-copying in JavaScript by zamalek on Thursday January 25, 2018 @03:47PM (#16234508)
> There are two places you can find in RAM that will contain that reference

That is an implementation detail completely depends on the VM. There is one very simple exception to your example: call inlining. Pass-by-reference is a behavior specification, not an implementation specification.

> Rust

If Rust emitted purely pass-by-value machine code, zero-cost-abstractions would be impossible in the language.

Re:Deep-copying in JavaScript by zzzcpan on Thursday January 25, 2018 @03:57PM (#16234594)
It's mostly about explicit vs. implicit. If a reference is implicit - it's pass-by-reference.
Re:Deep-copying in JavaScript by zamalek on Thursday January 25, 2018 @04:13PM (#16234725)
Not according to the comment that I am replying to:

> A reference is basically a pointer that the language prevents you from doing pointer arithmetic on, and in many languages such as PHP, is simply automatically dereferenced for you.

Also, the implicit is usually pass-by-value.

    function foo(a) { a++; }
    function bar(ref a) { a++; }
    b = 1;
    foo(b); // Pass by value, implicit.
    assert(b == 1);
    bar(ref b); // Pass by reference.
    assert(b == 2);
Heap vs. stack values are not the same thing as pass-by-reference and pass-by-value.
Re:Deep-copying in JavaScript by kmill on Thursday January 25, 2018 @03:47PM (#16234500)
> Is Rust pass-by-reference or pass-by-value? Well, the question is invalid, in either the original or the modern mutation of the meaning.

What do you mean? Maybe you mean "invalid" as in "no one should ask this anymore," but in case you mean "invalid" as in "is an apple an orange?" then

- It's strictly pass-by-value in the classic meaning. Sure, because of immutability there's the obvious optimization the compiler can do which is, under the hood, pass a pointer to a caller's value, but you could also implement everything by copying without the programmer noticing a difference (except for how long the program takes to run).

- It's strictly not pass-by-reference in the classic meaning. The "references" are a type of value. Parameters never are equivalent to the passed-in variable.

Whether or not it's a useful distinction to make is another story. References-as-values seems to be the emerging dominant paradigm for language design, but I sort of wish there were more languages that let you say "this variable is the fifth element of this array."

> if for no other reason than pass-by-X implies there's only two possibilities

I guess because people have only ever heard of by value and by reference, but there are a whole bunch more: by name, by copy-restore, by sharing.

Re:Deep-copying in JavaScript by shkkmo on Thursday January 25, 2018 @03:12PM (#16234161)
pass-by-value, pass-by-reference and pass-reference-by-value are all distinct.

PHP does all three, pass-by-value (simple values), pass-reference-by-value (objects and arrays), pass-by-reference (when using & prefix)

The terms still have important distinctions in modern languages as they are functionally different.

Re:Deep-copying in JavaScript by dragonwriter on Thursday January 25, 2018 @04:03PM (#16234649)
> Trying to answer this question in terms of "pass-by-X" doesn't help, if for no other reason than pass-by-X implies there's only two possibilities

No, it doesn't. Heck, when I learned pass- (or call-)-by-X there were three main values of X mentioned (and implicitly a near-universal number of possible alternatives): value, reference, and name.

There are actually several more recognized values; the Wikipedia article on Evaluation Strategy has a reasonably good list:

https://en.m.wikipedia.org/wiki/Evaluation_strategy

Re:Deep-copying in JavaScript by rising-sky on Thursday January 25, 2018 @03:34PM (#16234379)
You are correct, but it would so help to explain to the reader what the correct evaluation strategy employed by JavaScript is: call-by-sharing. https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sh...
Re:Deep-copying in JavaScript by ghusbands on Thursday January 25, 2018 @04:31PM (#16234867)
Not quite accurate. The primitive types (string, number, null, boolean, symbol, undefined) are passed only by value. Also, the page you link to says "the terminology is inconsistent across different sources", so it doesn't seem an ideal choice. Javascript is pass by value, with some of those values being references.
Re:Deep-copying in JavaScript by kmill on Friday January 26, 2018 @04:36AM (#16237962)
Would you know that some Javascript engines store primitives on the heap, so potentially it can all be described as call-by-sharing? Then again, they are immutable, so it is indistinguishable from call-by-value.

I think making these distinctions is somewhat asinine and that it doesn't really do more than make people aware that the function call interface actually has some interesting design considerations. It's sort of like "ok, we have decided whether a hamburger is a sandwich. Now we can finally do the thing that desperately depended on this decision, which was, uhh..."

Re:Deep-copying in JavaScript by jordache on Thursday January 25, 2018 @02:47PM (#16233951)
Don't know why you are being down voted. The author claimed EVERYTHING is pass by reference, which is false.
Re:Deep-copying in JavaScript by williamdclt on Thursday January 25, 2018 @03:33PM (#16234373)
It's not even close, nothing is passed by reference!
Re:Deep-copying in JavaScript by jordache on Thursday January 25, 2018 @04:24PM (#16234805)
objects? I don't care about low level engine implementation details. I'm saying from the dev's perspective, it's effectively pass by reference.
Re:Deep-copying in JavaScript by pjmlp on Thursday January 25, 2018 @05:20PM (#16235256)
It is only pass by reference if what ends up in the call stack is the address of the actual variable on the caller side, not what it points to.
Re:Deep-copying in JavaScript by globuous on Thursday January 25, 2018 @02:56PM (#16234020)
Wow, you got downvoted for being 100% right. Nothing in the first sentence nor the first code example is right. I haven't bothered to look at the rest ^^

JS doesn't pass everything by reference. As you've shown in your code example. And JS doesn't actually pass anything by reference as you and Amarshal have shown in your comments (which I knew, but didn't at the same time... Thanks for enlighting me guys!).

But what's mind blowing is that the code example given doesn't actually have anything to do with pass by ref of value. It's checking that the attributes of objects are reference based. It's not actually checking the function argument. Just an attribute of the argument.

I've upvoted your comment and your subcomment/reply. Not that you or anyone cares. They're just points. But it's a shame your comment is being greyed out.

Re:Deep-copying in JavaScript by aeharding on Thursday January 25, 2018 @02:32PM (#16233812)
EDIT: I am wrong. Below quote is irrelevant. I misunderstood the term "pass by reference", and confused it with mutable entities.

It is for objects, not primitives.

> JavaScript has 6 primitive data types: string, number, boolean, null, undefined, symbol (new in ES6). With the exception of null and undefined, all primitives values have object equivalents which wrap around the primitive values, e.g. a String object wraps around a string primitive. All primitives are immutable.

https://stackoverflow.com/a/13266769/1319878

Re:Deep-copying in JavaScript by amarshall on Thursday January 25, 2018 @02:37PM (#16233849)
The object is still passed by value, however the object itself contains references, which may be mutated. If objects were pass by reference then you’d end up with {a: 2} at the end:

    let a = {a: 1}
    
    function foo(a) {
      a = {a: 2}
    }
    
    foo(a)
    a //=> {a: 1}
Don’t confuse passing a mutable entity by value with pass by reference.
Re:Deep-copying in JavaScript by mnarayan01 on Thursday January 25, 2018 @03:58PM (#16234605)
> The object is still passed by value, however the object itself contains references, which may be mutated.

This would imply that:

  var v = 1;

  (function (o) {
    o.a = 2;
  }({ a: v });

  console.log(v);  // => 2
The whole "objects are pass-reference-by-value" is obviously annoying and confusing, but we're kind of stuck with it.
Re:Deep-copying in JavaScript by shkkmo on Thursday January 25, 2018 @04:16PM (#16234742)
Apparently there is another term (which I hadn't heard) which is: call-by-sharing

https://en.m.wikipedia.org/wiki/Evaluation_strategy#Call_by_...

Re:Deep-copying in JavaScript by kevincennis on Thursday January 25, 2018 @02:37PM (#16233851)
That's irrelevant. Look, same example but with an object.

    let a = { bar: 'baz' };
    
    function foo( a ) {
      a = { beep: 'boop' };
    }
    
    foo( a );
    
    console.log( a ); // { bar: 'baz' }
Re:Deep-copying in JavaScript by n0us on Thursday January 25, 2018 @02:52PM (#16233993)
Another way to think about it is that you just get a new reference to the same object, inside foo you are changing what 'a' refers to instead of what 'b' refers to. Using 'let' to declare 'b' is not necessary and using 'const' works just as well.

$ node

> const b = { bar: 'baz' }

> function foo(a){ a = {beep: 'boop'}; }

> foo(b)

> console.log(b)

{ bar: 'baz' }

>

Re:Deep-copying in JavaScript by lowkeyokay on Friday January 26, 2018 @02:48AM (#16237602)
I thought this was just a matter of scope. a declared outside of the function is not the same as the one declared as a parameter.
Re:Deep-copying in JavaScript by LoSboccacc on Thursday January 25, 2018 @02:41PM (#16233875)
that answer doesn't concern with the pass-by semantic, only with the primitive/object semantics.

this is the gist of the issue, fetched from http://javadude.com/articles/passbyvalue.htm about java but exemplifies perfectly the pass by reference semantics:

"If you can write such a method/function in your language such that calling

Type var1 = ...; Type var2 = ...; swap(var1,var2); actually switches the values of the variables var1 and var2, the language supports pass-by-reference semantics."

as java javascript is reference-by-value

Re:Deep-copying in JavaScript by Sawamara on Thursday January 25, 2018 @04:39PM (#16234929)
Primitive types and properties that are primitive types are pass by value, objects and functions are pass by reference.
Re:Deep-copying in JavaScript by k2xl on Thursday January 25, 2018 @05:34PM (#16235355)
It's still pass by value. The value of the object happens to be a reference to a memory location. A primitive also points to a memory location too.
Re:Deep-copying in JavaScript by windwake12 on Thursday January 25, 2018 @04:55PM (#16235065)
There's no difference

    let a = function bar() { };
    
    function foo( a ) {
      a = 2;
    }
    
    foo( a );
    
    console.log( a ); // bar
Re:Deep-copying in JavaScript by blitmap on Thursday January 25, 2018 @06:07PM (#16235600)
I thought this was because Javascript (by design) doesn't warn about shadowing identifiers.
Re:Deep-copying in JavaScript by chasingtheflow on Thursday January 25, 2018 @03:33PM (#16234368)
It is for objects, just not for primitives.
Re:Deep-copying in JavaScript by williamdclt on Thursday January 25, 2018 @03:35PM (#16234400)
No. Object are passed by value. Exact same example apply:

    let a = {key: 'a'};
    
    function foo( a ) {
      a = {otherKey: 'b'};
    }
    
    foo( a );
    
    console.log( a ); // {key: 'a'}
Re:Deep-copying in JavaScript by MJSplot_author on Thursday January 25, 2018 @03:42PM (#16234466)
But it is also true that:

    let a = {key: 'a'};
    
    function foo( a ) {
      a['otherKey'] = 'b';
    }
    
    foo( a );
    
    console.log( a ); // {key: 'a',otherKey: 'b'}
Re:Deep-copying in JavaScript by williamdclt on Thursday January 25, 2018 @03:59PM (#16234606)
Yes, because "a" is not an object, it is a reference to an object. This reference is passed by value. This kind of thing is why I'd recommand everybody to know C: when you know pointers there's no magic anywhere anymore
Re:Deep-copying in JavaScript by teamonkey on Thursday January 25, 2018 @05:56PM (#16235531)
Could you give an example in C of how the above works?
Re:Deep-copying in JavaScript by pjmlp on Friday January 26, 2018 @04:10AM (#16237869)
Something like this, without any kind of error checking being done.

    #include <stdlib.h>

    // assume some hash table library, exercise for the reader
    typedef struct{} *hashtable_t;
    extern hashtable_t hashtable_init(void);
    extern void hashtable_put(hashtable_t hashtable, const char* key, const char* value);
    extern void hashtable_dump(hashtable_t hashtable);

    typedef struct {
      hashtable_t table;
    } data_t;

    void foo(data_t* a)
    {
        hashtable_put(a->table, "otherKey", "b");
    }

    int main(void)
    {
        // let a = {key: 'a'};
        data_t* a = (data_t*) malloc(sizeof(data_t));
        a->table = hashtable_init();
        hashtable_put(a->table, "key", "a");

        foo(a);

        // console.log( a );
        hashtable_dump(a->table);
        return 0;
    }

The function foo() gets the numeric value of the a pointer, thus a parameter inside foo() points to the same memory location.

If C had pass-by-reference, it would be possible to give (implicitly) the memory location of the local variable a in main() instead. For example, like in Pascal (var) or C++ (& in function declaration).

Re:Deep-copying in JavaScript by shkkmo on Thursday January 25, 2018 @03:52PM (#16234560)
Yes, which together with the other example shows that javascript uses pass-reference-by-value, as explained elsewhere on the thread.
Re:Deep-copying in JavaScript by zzzcpan on Thursday January 25, 2018 @03:42PM (#16234458)
From a user perspective most languages make a mess out of these things and confuse people. In Javascript certain things are declared in a similar way, but some behave like values and some behave like references. Which makes it both pass-by-value and pass-by-reference.
Re:Deep-copying in JavaScript by pjmlp on Thursday January 25, 2018 @03:58PM (#16234604)
Wrong from CS point of view, references are also pass-by-value on JavaScript.

If JavaScript allowed pass-by-referece, we would be able to do the following,

    function swap(x, y) {
        let c = x
        x = y
        y = c
    }

    let a = {a: 6, b: 7}
    let b = {c: 8, d: 8}

    swap(a, b)

    console.log(b)

    // Object {a: 6, b: 7}
Meaning, pass-by-reference means being able to actually change the "pointer" used by the local variable.
Re:Deep-copying in JavaScript by zzzcpan on Thursday January 25, 2018 @04:11PM (#16234714)
I understand what you mean, but consider this to be an incorrect view on these things. They are not about CS, but about user experience.
Re:Deep-copying in JavaScript by pjmlp on Thursday January 25, 2018 @05:08PM (#16235159)
The incorrect view is to teach wrong concepts just because some people rather learn based on gut feeling, than taking the effort to learn it properly.
Re:Deep-copying in JavaScript by shkkmo on Thursday January 25, 2018 @03:56PM (#16234586)
I believe that javascript always uses pass-reference-by-value, but simple types are immutable, which means that pass-reference-by-value is functionally identical to pass-by-value since there is no way to make changes to the immutable referent.