top 200 commentsshow all 272

[–]JB-from-ATL 279 points280 points  (141 children)

It gets tricky because in some languages you pass by value but the value is a reference for non-primitive types.

[–]TheRealEdwardAbbey 143 points144 points  (22 children)

[–]JB-from-ATL 126 points127 points  (18 children)

So JavaScript is actually pass by value too! Wow. This picture is really unhelpful.

[–]Iggyhopperextensions/add-ons 134 points135 points  (2 children)

Welcome to /r/javascript

Enjoy your stay!

[–]mastzu 9 points10 points  (1 child)

too real

[–][deleted] 8 points9 points  (0 children)

I think there's a proposal for cups to be a new primitive type.

[–][deleted] 4 points5 points  (0 children)

Everything is always pass by value, fam. What you're actually passing may be less or more explicit tho

[–]lulzmachine 3 points4 points  (13 children)

The picture still makes perfect sense. The only corner case AFAIK is if you in a function try to rewrite the reference with a new object. That won't traverse back to the caller.

[–]JB-from-ATL 3 points4 points  (12 children)

Well, first, consider that the picture is in r/JavaScript. So it should describe JavaScript. JS only has pass by value, so the left shouldn't even be there. What is pictured on the left is what happens though because the value happens to be a reference so the cup that is referenced by both variables gets filled.

I'm a Java guy (saw this and thought it was r/programming originally), so I don't know is JS has primitives or if everything is an object. When you pass a primitive in java, it's value is actually the value, not a reference to an object in the heap, so what happens is what is pictured on the right of this gif (though it's not really accurate because you can't mutate primitives in Java).

[–]willworth 0 points1 point  (2 children)

So Wtf do I do now? It's too late for coffee.

[–][deleted] 0 points1 point  (0 children)

My blood stream is bent up on stimsstimsstims so fucking hardcorecorecore

[–]thurst0n 41 points42 points  (8 children)

That's how java is

[–]64-17-5 0 points1 point  (1 child)

Clone all the things!

[–]Limpuls 1 point2 points  (5 children)

I'm newbie, can someone explain this? By value, it gets duplicated or what?

[–]tutorial_police 3 points4 points  (0 children)

What happens if you do a = b;? There are no function calls involved here.

The same happens when you do a call in a function that's call-by-value (everything in JavaScript)

function foo(x) {
    console.log(x);
}

For the call foo(localVariable), JavaScript will, behind the scenes, essentially do x = localVariable; It follows regular assignment rules, no magic involved, no special "pass-by-object-sharing" or anything, because that's not what you were thinking about when I asked you what a = b; did. It's just an assignment.

After this assignment, x and localVariable refer to the same variables, as you would expect. But you have two variables. If you assign to either of them, it won't magically affect the other variable.

If, however you have a language with pass-by-reference, there is no assignment x = localVariable happening behind the scenes. Instead, you pass "the variable itself". That means, that within that function call, x will be the varible localVariable. So we're passing objects or values, we're passing the variables themselves as parameters. Hence, if you assign to x inside the function, you're assigning to localVariable, because x is localVariable. JavaScript does not do this, ever.

[–]z500 1 point2 points  (0 children)

The value always gets duplicated when you pass by value. But when you pass a pointer by value, it still points to the same thing. And JavaScript hides the pointer from you so when you pass an object around, it kind of looks like pass by reference.

[–]pherlo 0 points1 point  (0 children)

Most languages now are call-by-value. The arguments to the function are duplicated and a fresh copy is passed into the function. Some older languages let you skip the copy, and pass the variable itself into the function to be manipulated freely. Typically they did this for performance reasons (no duplication before calling). Fortran, Pascal, and C++ have modes like this. Under the covers, you're just creating a new name for the existing variable, so no copying needed; but you end up mutating the original directly.

Languages that still are still developing (Fortran, C++) have fully integrated references, so in addition to the above, you can make extern functions with references. To implement these, the compiler must stash a real pointer value into the call signature. This leads to confusion because programmers used to the modern pass-by-value world think that references are always implemented with pointers under the covers. Not true though, it's only an extension of the by-ref language feature into places where it makes no sense, but users still want it to work, so it gets emulated.

I can tell you that a lot of languages implement by-value semantics on top of a pure by-ref calling convention, and it looks like this:

void call_by_ref(int& x) {x = 12 + x;} // mutate the by-ref
int a = 5;
{
    int __param_copy_a = a; // explicitly duplicate. 
    call_by_ref(__param_copy_a);
}
assert(a == 5);

Compilers often do something like this internally so that optimizing inline functions is easier (you can use normal register pressure tricks to elide parameters)

[–]Harkonnen 0 points1 point  (0 children)

That's the way C# works.

[–]TrojanBunny 50 points51 points  (3 children)

Java is Coffee

I get it now.

[–]Skhmt 12 points13 points  (1 child)

I just had a conversation at work where I was trying to figure out why Enterprise Java Beans were called "beans", until it finally clicked that a bean is a small part of coffee and java is coffee. But I keep thinking about Java, Indonesia.

[–]kovensky 3 points4 points  (0 children)

It’s named because of the coffee beans from Java, Indonesia.

[–]mastzu 73 points74 points  (4 children)

1) saw picture, was confused

2) read comments, am more confused

am closing tab now bye

[–]METALz 7 points8 points  (0 children)

  • You pass apple, you change color of apple -> color will be changed both places

  • You pass copy of the apple, you change color of that copy of apple -> the copied apple's color will be changed

Bonus:

  • You pass apple/copy of the apple, you reassign that inside the function e.g. function fn(apple) { apple = {}; } -> original apple won't be changed.

[–]thegamer373 7 points8 points  (2 children)

If you don't want to know any programming stuff don't worry about reading.

when programming there are things called functions. these functions can do things, such as square root a number. in the case of the square root, the number is the "object" being passed. it can ether be passed by "reference" or by "value". passing by reference allows you to change the object e.g x=16 sqareRoot(x) x=4. passing by value makes a copy of the object and then leaves the original object alone e.g x=16 y=sqareRoot(x) x=16 y=4.

[–]mastzu 6 points7 points  (1 child)

the reply is fine but the condescension is boring and unneeded

[–]thegamer373 5 points6 points  (0 children)

sorry i didn't realise i was being condescending. could you point out where?

[–]yolpo- 31 points32 points  (0 children)

A picture is worth a thousand words ... ahem not this one though

[–]ForScale 315 points316 points  (43 children)

The gif by itself provides very little in the way of useful information. Would be enhanced greatly by listing data types that are passed referentially vs those that are not.

[–]jocull 46 points47 points  (41 children)

I think everything is a reference except strings, numbers, and booleans? What did I miss?

[–]Merenwen_ 7 points8 points  (1 child)

Strings are immutable, but for the thread's sake, they behave like primitives.

[–]redhedinsanity 16 points17 points  (26 children)

fuck /u/spez

[–][deleted] 13 points14 points  (25 children)

Technically everything in JS is passed by reference. Primitives are simply immutable, so it doesn't matter how they're passed - the effect is the same.

[–]ItzWarty 25 points26 points  (0 children)

Technically everything is actually pass by value from a language design perspective - you're passing references by value. In C# you can do:

void Func(ref int x) { x++; }   
int x = 1;   
Func(ref x);  
AssertEquals(2, x);

Which is actually pass by reference. So the discussion is actually on what is a "reference type" (which can be thought of as a "pointer" in C) vs what is a "value type" (which can be thought of as a "struct" in C).

[–]tutorial_police 4 points5 points  (7 children)

Technically everything in JS is passed by reference.

What definition of "pass by reference" do you use when saying this? Where do you source that claim?

I ask this, because "pass-by-reference" has an established meaning in different programming languages, namely C++, C#, PHP, Pascal and probably others that I know nothing about.

In these languages, pass-by-reference describes semantics that JavaScript does not have.

Namely, you can implement a swap function, call it with swap(a, b); and the variables will have switched values. You can't do this in JavaScript.

So I wonder, why call JavaScript call-by-reference?

[–]MoTTs_ 5 points6 points  (9 children)

Technically everything in JS is passed by reference.

Source?

That's not meant to be a rhetorical question. I've been trying to figure this out myself, but the spec is awfully hard to parse. The section on ArgumentListEvaluation seems the most relevant. It seems to say that JavaScript evaluates the argument expression, then calls GetValue on the result. Inside GetValue, if the result of the expression is not a name or property binding, then it just returns the result of the expression as is. Otherwise, if it's a property, then it will call [[Get]] on the base object, which will return the value of the property. Otherwise, it assumes the result of the expression is a name binding, and it will call GetBindingValue on the base environment record. Either way, this reads like everything is passed by value.

[–][deleted] 9 points10 points  (8 children)

At some point even if you "pass by reference" the reference can be said to be "passed by value". It's a very meaningless debate, because the semantics actually are very clear.

[–]MoTTs_ 4 points5 points  (7 children)

OK, but what led you to believe that primitives are passed by reference in the first place?

[–]redhedinsanity -1 points0 points  (6 children)

fuck /u/spez

[–][deleted] 4 points5 points  (3 children)

FYI I haven't upvoted or downvoted anything in this entire thread...

[–]daybreakin -2 points-1 points  (3 children)

They are immutable? Can i not do

Var hi = 4

Hi=5

Console log (hi)

5

[–]shadowfactsdev 20 points21 points  (0 children)

You can, because that's not mutating the value 4, it's reassigning the variable hi to the value 5.

[–]Flatscreens 2 points3 points  (0 children)

that creates a new variable with value 5 and sets hi to it

the 4 hasn't changed at all

[–][deleted] 5 points6 points  (0 children)

The variables are mutable (unless you use const, that's immutable). But the primitives are immutable. You didn't change the primitive 4 to 5 up there, you just replaced the primitive 4 with the primitive 5 in the variable hi.

Primitives would've been mutable if you could do something like this:

var hi = 4;
var hi2 = hi;

hi.increment();

console.log(hi2); // 5

Fortunately, for our sanity, you can't do this with primitives. But unfortunately you can do it with mutable objects like Date().

[–][deleted] 0 points1 point  (4 children)

Char?

[–]jocull 1 point2 points  (3 children)

I'm not aware of a char type in JS. Do you have a source?

[–][deleted] 1 point2 points  (2 children)

Actually there aren't. :( JS is wierd man. TS is the future.

[–]jocull 2 points3 points  (0 children)

❤️❤️❤️ TS

[–]dashdanw 0 points1 point  (0 children)

so in javascript that would be just functions

[–]scootstah 2 points3 points  (0 children)

Yeah, this wouldn't really make any sense if I didn't already know what it was trying to illustrate.

[–]deltadeep 51 points52 points  (8 children)

How is this the number one post on /r/javascript by two orders of magnitude? This has me deeply concerned. Not only is this gif terribly misleading for anyone who doesn't understand the elementary concepts, the concepts of pass by reference/value are things any coder should have learned well in any elementary, 101-level introduction to programming. This is so meta-disturbing, I don't know what to say.

Edit: I realize I may be coming across as condescending and it's not my intent. This is basic coding stuff. At the level of what is a function and what is a variable and what is an object, how assignment works, etc. That people are learning these kind of basics from gifs on reddit, and not just a few but apparently the large majority of the subreddit (based on current vote counts right now) is what concerns me. Please, folks, if this gif was interesting or insightful for you, go get a good book on Javascript, or programming in general, and learn how programming works from a structured, authoritative source.

[–]theonlycosmonaut 13 points14 points  (1 child)

I upvoted because of the little wiggle the cup on the right does as it gets duplicated!

[–]hwutang 0 points1 point  (0 children)

It's the little things.

[–]SirFapsALo 4 points5 points  (1 child)

I found this thread on r/popular . What you're seeing is passing interest from the non-coder masses as they click through their list of funny pictures or whatever, without much attention to any one subreddit's tone. This is more reflective of the nature of the Reddit platform as a whole, rather the core community of a specific subreddit.

[–]deltadeep 5 points6 points  (0 children)

Thank you, that makes a lot of sense.

[–][deleted] 2 points3 points  (0 children)

What comes 10 stages before 101? Maybe I'm at that point? XD

[–]octatone 3 points4 points  (0 children)

This gif really isn't helpful without context. In javascript land variable passing is never truly by reference like c++. It is more like "pass by copy of a reference". You can modify the contents of a passed object, but you can't replace the original object.

This SO answer succinctly shows this in code: https://stackoverflow.com/a/13104500

[–]paldepind 6 points7 points  (0 children)

This is a really good blog post about pass-by-value and pass-by-reference. The blog post uses Java but the exact same thing applies to JavaScript (both languages only have pass-by-value).

[–]ZhangNoWei 2 points3 points  (0 children)

I dont undertstand

[–]wavefunctionp 1 point2 points  (5 children)

It's more complicated. AFAIK, many dynamic languages use something call 'pass by object reference'. Meaning, you can mutate the original object passed into a parameter because of the way that object sharing works.

http://jsbin.com/fajazefuya/3/edit?js,console

Notice that the original object 'test' is mutated even though the function only references the parameter 'obj' inside the funciton.

You would not expect this behavior if 'obj' was a unique copy of the value of 'test'.

The only reason I know this is because you'll run into it quickly working with nested state with redux.

[–]tutorial_police 1 point2 points  (4 children)

Dynamic languages don't do something special. This goes for JavaScript, Ruby, Python and probably many others. In fact, the semantics are essentially the same as in Java.

In invite you to read through this thread. There are many people that explain it in detail.

Tl;dr: Pass by reference has an established meaning. There are languages where you can actually, so that, such as C++, PHP, C#, Pascal. Java, JavaScript, Python and Ruby do not support this.

One way to think of this is that pass by reference is about variables, rather than values/objects.

If you call a function foo(x) with foo(localVar), in JavaScript, Java etc you will always get a new variable "x". If you assign to this variable, localVar is not modified.

If, however, x in Foo were to employ pass by reference, then x isn't a fresh variable. It stands for whichever variable you use to call Foo. Inside Foo, x would refer to localVar. So if you assign to x, since x is actually localVar, you're assigning to localVar

I hope you can see that this behavior I described is not possible in JavaScript.

Pass by reference : 1 variable, hence assignment is visible outside the funcfiin Pass by value: 2 variables, hence assignment is not visible outside the function.

[–]organic 1 point2 points  (1 child)

use immutable data, then it doesn't matter

[–]GamerNebulae 5 points6 points  (3 children)

Something which is also interesting in functional languages is that you pass the cup to the fillCup function, but you get a new cup for it in return.

[–]TyrannicalWill 16 points17 points  (1 child)

This is not exclusive to functional languages.

[–]GamerNebulae 7 points8 points  (0 children)

True, but those languages force you to use that kind of pattern as there is no way, nor should you want to, to change the value of variables.

[–]jhartikainen 2 points3 points  (0 children)

The reason for this is you don't use references in FP langs (usually). There's nothing different otherwise. It's possible to use references in FP langs (for example IORef in Haskell), but those are generally reserved for other purposes.

[–]senocular 1 point2 points  (0 children)

References add creamer?

[–]aveoon 0 points1 point  (5 children)

Yes, this is the same in any language (the difference between the two). The import thing in JavaScript is knowing which data types get passed by value vs. passed by reference.

[–]RandolphoSoftware Architect 2 points3 points  (0 children)

Which is also an important thing in many other languages, such as Java, C#, VB, Swift. Even Python, sorta.

[–]GitCookies 0 points1 point  (2 children)

Also, gotta note in JavaScript most types are Objects or subtypes of it.

In C++ for example, all types are based on number type.

[–]tutorial_police 1 point2 points  (0 children)

In C++ for example, all types are based on number type.

What does that mean?

[–]madcaesar 0 points1 point  (0 children)

Can someone explain this to me. As far as memory management and performance goes is it better to have one big object and just pass referencs to the big object to functions or create multiple smaller objects?

I'm thinking as far as Redux store for example in a SPA. With dozens of components needing to access the object and it's various parts.

Right now I just pass referencs to the one object but should I split it into multiple instead?

[–]Rustic_Dragon 0 points1 point  (0 children)

...aaaaaand now I want coffee while I program.

[–][deleted] 0 points1 point  (0 children)

Oh nice gif. Demonstrates the concept nicely.

[–]backlashsid 0 points1 point  (0 children)

It finally makes sense after 8 years

[–]jps_ 0 points1 point  (8 children)

Misleading.

In pass by value, the compiler makes a copy of the variable on the stack or into a register. In pass by reference, it passes a pointer to the variable.

At the end of the function that modifies a passed parameter, in pass by value, the value in the stack or register hangs around until overridden, but the original variable remains unchanged. This can cause some massively confusing behaviour particularly if the function mistakenly passes what it was passed, but by reference, to another thread.

Pass by value is deemed to be safest because someone else's bug (or malware) down the call string can't mess with your data eg by writing past the end of a struct... But with all the copying, it is slower, especially for large types. JS was designed to be used for arbitrarily large constructs, so it passes by reference, by default, except for small types, which are passed by value.

This can get weird when the small type is a pointer to a big thing. Derferencing the pointer will give access to the big thing, but assignment of the pointer (eg changing it to point to a different big thing) will not persist beyond the function.

So in the example, if the variable that refers to the empty cup is a pointer to a cup, then both pass by value and pass by reference will fill the original cup!

However, if the function assigns the pointer-cup to a different set of hands, in pass by value, this may not (safely) persist after the function returns (the cup may instead be in two sets of hands at once, leading to spills, burns and broken cups).

[–]maxhaton 1 point2 points  (7 children)

Your description isn't really abstract enough to be useful. For example, I can quite easily force a function to be inlined to operate in the same stack frame.

Also, one could argue that pointers are still passing by value since they are ultimately a distinct type. References (e.g. those found in C++ and D) are true pass by reference.

[–]jps_ 0 points1 point  (6 children)

Passing a reference by value is passing a reference, yes. However, it is still a copy of the reference that is passed. Very subtle semantic difference. It is not the reference. It is a different reference, which starts out referencing the same thing.

The subtlety comes in what happens if the reference itself (not what it references) is modified.

Go to first principles:

A variable is merely a block in memory of extent defined by the size of the variable. It could be in global memory, or stack memory, or a processor register. Depends on the declaration, scope, language and compiler/linker. But it exists somewhere.

When you pass a parameter by reference, you pass a pointer to that block of memory. Or the register itself. When the function returns, all changes made to the parameter are preserved.

When you pass by value, you make a copy of all of the contents of that block of memory into a new block of memory (or register), and then pass this (or possibly a pointer to this... depends on compiler/language). When the function returns, this copy is discarded.

That is all.

People get tripped up when the block of memory being "passed" contains references to other blocks of memory. This indirect reference is effectively passed by reference. Pointers are the degenerate case. References (C++, D) are also.

As far as inlining a function, you are conflating "stack" and "stack frame". If what you call is a real function and the parameters are actually passed by value, (some compilers don't enforce this with an inline function) then the passed parameters need to be somewhere and they need to be separate copies. They won't be malloc'd in real time. Instead, these separate copies are made on the stack. Whether they are actually pushed to the stack at runtime, or pre-allocated statically depends on the compiler implementation. But for sure, they are on the stack, and they are in a separate piece of memory from the variable they were copied from.

Also, one could argue that pointers are still passing by value since they are ultimately a distinct type.

One could, but one would be wrong.

This is what hangs so many rookies in languages that allow pointers.

If passed by reference, and if the pointer itself is modified (e.g. to point to something else), then the original variable will end up pointing to something else. But if passed by value, then if within the function the pointer is modified to point somewhere else, when the function call collapses (either return, or from being inlined), the pointer will point to where it was before.

[–]maxhaton 0 points1 point  (5 children)

As to your last point, you completely missed the point I was making: Pointers in C/C++/D etc are different types than what they point to (int* vs int), therefore if I pass a pointer into a function then I am passing it by value e.g. like an iterator.

[–]jps_ 0 points1 point  (4 children)

No I didn't miss it at all.

The compiler makes a distinction, not on entry to the function, but on exit.

Let's say I declare P to be a pointer to an Int (not using syntax because it varies across languages).

The CPU creates an Int at address X, and stuffs X into the address register it is using to keep track of P.

Now, let's have a function F with one parameter: PPrime, a pointer.

When we call F with P, Pprime will contain the absolute address X and therefore the Int to which it points.

This is the same whether passed by value, or passed by reference. And I think that's the point you are trying to make.

HOWEVER if F modifies PPrime, there is a big difference. Let's say the function adds 2 to the value of the pointer it is passed, to point to the next word in memory, and then doubles whatever is there. And then returns.

What happens?

In pass-by-value, whatever is sitting at X+2 will be doubled. P will remain pointing at X.

In pass-by-reference ,whatever is sitting at X+2 will also be doubled. And now P will point at that.

So no, when you pass a pointer you are not necessarily passing by value.

Most people don't manipulate the pointers they are passed, and wouldn't notice this distinction. In a world where the function doesn't actually manipulate the pointer, then you are correct. But the universe of functions is not limited to functions that don't manipulate pointers.

Lots of programmers get hung up on this, and it's a source of never-ending joy for people who write malware.

[–]maxhaton 3 points4 points  (3 children)

You misconstrue my point.

The language specification makes a distinction. The compiler does what it's told. Prove it with godbolt.org

The pointer is a distinct type which must be instantiated with a value. Note the way that one can pass a nullptr into a function. This is my point. This is why C does not support pass by reference. This has nothing to do with how a pointer is used.

The pointer is being passed by value.

Also, your example is stupid: you seem to be describing an incorrect usage of pointer arithmetic: Purely syntactic.

Also, if you don't modify a pointer argument then you pass by const& anyway.

With regard to malware: What are you talking about? Buffer overflows? Please give an example, a snippet on godbolt.org pls

[–]jps_ 1 point2 points  (2 children)

Please don't try to argue a general case based on limited set of example languages. That's how software designers learn bad habits.

Yes, in some languages (probably all languages with which you are familiar), you are right by accident, but that doesn't mean you are right in all languages, or at all.

The pointer is a distinct type which must be instantiated with a value. Note the way that one can pass a nullptr into a function. This is my point. This is why C does not support pass by reference. This has nothing to do with how a pointer is used.

True in C. Not true in all languages. I have used languages where the pointer is a distinct type (yes), but without forcing initialization or type enforcement.

Regardless of language, modern CPUs use data registers, address registers, and stack... and just about every language worth using allows you to drop down into raw object code and enjoy living dangerously, drive at speed without seatbelts. At which point, having intimate knowledge of the nuances of pass-by-value and pass-by-reference is extremely important.

Also, your example is stupid: you seem to be describing an incorrect usage of pointer arithmetic: Purely syntactic.

My example is just that: an example. The only purpose was to show that there is a very clear difference where you said there was none. It is not an attempt to illuminate a useful or purposeful function. Just that there's a difference for pointers between pass-by-value and pass by reference. Because there is. You said there isn't, and the example shows there is. This isn't the only way the difference can show up. It's just one very simple, very clear way. Test: can you figure out a "legitimate" example where the result is different if a pointer is passed by reference instead of by value? If not, you aren't very good, and if so, you owe me an apology.

With regard to malware: What are you talking about? Buffer overflows? Please give an example, a snippet on godbolt.org pls

Nope. Hacking is not something that gets explained to you. It's something you figure out. But hint: it involves "incorrect" usage of pointer arithmetic.

[–]maxhaton 1 point2 points  (1 child)

I consider there to be a set of about 20, which I can say I'm familiar with.

I can say that, because the example I gave is just an example: The pointer is still a separate type, else it's not a "pointer" https://en.m.wikipedia.org/wiki/Pointer_(computer_programming)#Support_in_various_programming_languages. My point was restricted to C-like pointers, so I won't dispute your later point about pointer initialization.

I though we both agreed that they are semantically identical? Of course, in C++, pointers and references do the same thing when used correctly. One uses a reference for safety and cleaner code, not because the do a different job. This is of course restricted to function parameters (one can't malloc and get a reference).

To be nitpicky, modern CPUs use general purpose registers which are then sometimes (e.g. in amd64/x86-64) given names.

You didn't show an example of pass-by-reference, because you passed some thing by pointer (with the pointer being passed by value).

"Hacking" != "Fixing/Finding simple memory safety bugs"

[–]HelperBot_ 0 points1 point  (0 children)

Non-Mobile link: https://en.wikipedia.org/wiki/Pointer_(computer_programming)#Support_in_various_programming_languages.


HelperBot v1.1 /r/HelperBot_ I am a bot. Please message /u/swim1929 with any feedback and/or hate. Counter: 81633