8 ms·
JavaScript is absolutely not pass by reference. let a = 1; function foo( a ) { a = 2; } foo( a ); console.log( a ); //
by kevincennis 9y ago
JavaScript is absolutely not pass by reference.
let a = 1;
function foo( a ) {
a = 2;
}
foo( a );
console.log( a ); // 1
- aeharding 9y agoEDIT: 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 https://stackoverflow.com/a/13266769/1319878
- amarshall 9y agoThe 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.
- mnarayan01 9y ago> 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.
- shkkmo 9y agoApparently there is another term (which I hadn't heard) which is: call-by-sharing https://en.m.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing https://en.m.wikipedia.org/wiki/Evaluation_strategy#Call_by_...
- kevincennis 9y agoThat'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' }
- n0us 9y agoAnother 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' } >
- lowkeyokay 9y agoI 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.
- LoSboccacc 9y agothat 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 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
- jerf 9y agoNowadays, 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.
- shkkmo 9y agoWhat are you talking about? PHP has pass-by-reference: http://php.net/manual/en/language.references.pass.php http://php.net/manual/en/language.references.pass.php
- jerf 9y agoAnd 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.
- jordache 9y agoDon't know why you are being down voted. The author claimed EVERYTHING is pass by reference, which is false.
- williamdclt 9y agoIt's not even close, nothing is passed by reference!
- jordache 9y agoobjects? I don't care about low level engine implementation details. I'm saying from the dev's perspective, it's effectively pass by reference.
- pjmlp 9y agoIt 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.
- globuous 9y agoWow, 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.
- chasingtheflow 9y agoIt is for objects, just not for primitives.
- williamdclt 9y agoNo. 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'}
- MJSplot_author 9y agoBut it is also true that: let a = {key: 'a'}; function foo( a ) { a['otherKey'] = 'b'; } foo( a ); console.log( a ); // {key: 'a',otherKey: 'b'}
- shkkmo 9y agoYes, which together with the other example shows that javascript uses pass-reference-by-value, as explained elsewhere on the thread.
- williamdclt 9y agoYes, 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
- teamonkey 9y agoCould you give an example in C of how the above works?
- pjmlp 9y agoSomething 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).
- rising-sky 9y agoYou 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_sharing https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sh...
- ghusbands 9y agoNot 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.
- kmill 9y agoWould 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..."
- zzzcpan 9y agoFrom 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.
- shkkmo 9y agoI 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.
- pjmlp 9y agoWrong 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.
- zzzcpan 9y agoI understand what you mean, but consider this to be an incorrect view on these things. They are not about CS, but about user experience.
- pjmlp 9y agoThe 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.
- j4ship 9y agounless you pass an object ..... then it is its partial pass by reference. Is HN the place to get wrong information, this is an example of what is going on here. How is this not completely downvoted out of oblivion https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language https://stackoverflow.com/questions/518000/is-javascript-a-p...
- Sawamara 9y agoPrimitive types and properties that are primitive types are pass by value, objects and functions are pass by reference.
- windwake12 9y agoThere's no difference let a = function bar() { }; function foo( a ) { a = 2; } foo( a ); console.log( a ); // bar
- k2xl 9y agoIt'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.
- andrewstuart2 9y ago"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.
- pjmlp 9y agoEverything 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.
- andrewstuart2 9y agoIsn't that what I said? That's what I was trying to say, at least, but keeping the language more js-oriented.
- ZeroBugBounce 9y agoI'm not the parent commenter but yes, you both made the same distinction as far as I can tell.
- Stratoscope 9y agoIt 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++.
- blitmap 9y agoI thought this was because Javascript (by design) doesn't warn about shadowing identifiers.