14

Since strings in JavaScript are basic types, does passing a string to a function create a local copy of it? I'm wondering about this since you can't modify strings after they've been created, so it would seem illogical that JavaScript VMs wouldn't just pass the string's address to the function internally.

If anybody is going to tell me that i shouldn't worry about this (this happens a lot when talking to web developers), I'm working on HTML5 games and garbage collection is a major concern, so i really need to know.

Ian
  • 50,146
  • 13
  • 101
  • 111
dreta
  • 1,016
  • 3
  • 13
  • 22
  • 4
    Maybe a silly question, but why don't you just try it? – ulentini Mar 27 '13 at 16:46
  • 2
    Every primitive type are passed by value. See http://snook.ca/archives/javascript/javascript_pass –  Mar 27 '13 at 16:47
  • @silentboy: String values may be treated like primitives, but I *guarantee* you, the string is not passed by value. – T.J. Crowder Mar 27 '13 at 16:51
  • Acctually when passing primitive from object, its passed by reference. But if you passed it like a variable its passed by value. If not i would like to see an example. @t.j. Crowder –  Mar 27 '13 at 16:58
  • @silentboy: My statement above is somewhat open to misinterpretation. JavaScript is **purely** a pass-by-value language. What I meant was, I *guarantee* you that the value passed for a string is some kind of reference to the underlying characters, not a *copy* of the characters. Doing anything else would be a very silly implementation, as string values are immutable. – T.J. Crowder Mar 27 '13 at 17:00
  • If you think garbage collection is a big problem. Always use a `delete` statement with newly created object. –  Mar 27 '13 at 17:16
  • 1
    @silentboy: `delete` has absolutely nothing to do with garbage collection. This isn't C++, JavaScript's `delete` means something completely different. – T.J. Crowder Mar 27 '13 at 17:21
  • 1
    Because strings are immutable, it doesn't matter. If they are passed by reference, changes to the reference do not affect the original string, but neither does anything you do to the original. All you can do is read the original, or create a new String based on the original. – kennebec Mar 27 '13 at 17:45
  • @Uby how can i test if a string is passed by address by the JS VM? can't do that is JS for sure. 4 upvotes on that comment, i must be missing something – dreta Mar 27 '13 at 22:50
  • @dreta Actually, after reading all answers and comments I realized that mine *was* a silly question. And I really don't know why I got 4 upvotes :P – ulentini Mar 28 '13 at 07:22

2 Answers2

13

The string will be passed by reference.

A string is not mutable so whenever you try to change it you get a new string (eg. by doing value+="more").

Also see: What does immutable mean?

@T.J. Crowder: by value vs by ref - if you are looking at the language definition you are correct. However I don't think there is an implementation that actually creates a copy of the string because it would be incredibly slow. Also since strings are immutable primitives there is no need to copy them since they can't change.

Community
  • 1
  • 1
laktak
  • 57,064
  • 17
  • 134
  • 164
  • 2
    *"The string will be passed by reference."* You state that as fact. Do you have any evidence for it? I believe it's true (or more accurately, I believe a reference to the string is passed by value, **nothing** in JavaScript is "pass by reference"), but without being able to cite something, I would hesitate to state it as bald fact. – T.J. Crowder Mar 27 '13 at 16:58
  • @ Chris: I'm not saying a copy of the contents of the string are copied. I'm reasonably certain they aren't (as I said in my answer), that a reference to those contents is passed (by value) into the function. – T.J. Crowder Mar 27 '13 at 17:15
  • i know strings are immutable, i said that in the question, that's why i asked it in the first place. i'll probably accept this answer tomorrow, unless somebody can give reference. answer's based on common sense, though i guess it's hard to ask for more when it comes to these things. – dreta Mar 27 '13 at 22:59
  • *"However I don't think there is an implementation that actually creates a copy of the string because it would be incredibly slow."* I never said I thought an implementation did that. I said quite the opposite in my answer, in fact. – T.J. Crowder Nov 02 '17 at 08:25
  • What about assignments ? Is a string variable's value cloned on assignment, or is a reference to that string's value copied ? I am assuming that's by reference as well, but this part from the book You Don't Know JS says otherwise: `Simple values (aka scalar primitives) are always assigned/passed by value-copy: null, undefined, string, number, boolean, and ES6's symbol.` [Here](https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch2.md) is the link to the specific chapter (I would jump to the "value vs reference" part immediately). – doubleOrt Nov 06 '17 at 15:18
  • What about other primitives ? Are other primitives assigned/passed by reference as well ? It appears to me that it would make the most sense to do it that way, because since all primitives are immutable, I presume it would not make a difference aside from the by-reference way being more memory efficient (for certain types, I assume). Where am I wrong ? Where am I not wrong ? – doubleOrt Nov 06 '17 at 15:39
  • @Taurus as your comment looks like a question on it's own - why don't you post it? – laktak Nov 06 '17 at 21:22
  • Which comment ? – doubleOrt Nov 06 '17 at 21:25
  • @Taurus I meant that you should post your own question instead of commenting here. – laktak Nov 06 '17 at 21:34
  • Yeah, I get that. But you said make a question out of your comment and i have 2 of those, so i asked of which comment should i make a question ? Or are you being more general ? – doubleOrt Nov 06 '17 at 21:36
6

I believe the specification is silent on this point. However, it would be a truly idiotic implementation that passed the actual content of the string rather than passing a reference to that content in memory, even if strings are theoretically "primitives". I suspect most implementations treat "primitive" strings much as they treat object references (in this regard, obviously not in some others, such as ===), but just not with the Object trappings.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • If a reference to something is passed, then wouldn't it be more reasonable for `b` in the following example to have a `bar` property as well ? `var a = "foo" var b = a; a["bar"] = "baz"; console.log(b["bar"]);` Now, I am certain there is something up with the boxing that is causing this confusion for me, what is it? – doubleOrt Nov 01 '17 at 20:25
  • @Taurus: This is a confusing part of JavaScript, but it's covered by the spec. :-) Remember that JavaScript has both string *primitives* and, separately, string *objects*. `a` [contains / has a reference to] the *primitive* string `"foo"`. The statement `a["bar"] = "baz"` gets the primitive string from `a` but since it then uses that like an object, a new temporary string object gets created and used for that part of the expression. That temporary string object gets the `bar` property, but since nothing saves... *(cont'd)* – T.J. Crowder Nov 01 '17 at 22:23
  • *(continuing)* ...that object's reference anywhere (not to `a`, and certainly not to `b`), the object is immediately available for garbage collection. Meanwhile, `a` (and `b`) still [contains / has a reference to] the *primitive* string `"foo"` which, being a primitive, doesn't (can't) have ad hoc properties. This behavior is described in the abstract [PutValue operation](https://tc39.github.io/ecma262/#sec-putvalue) in the spec. We can observe the creation of the string object by adding a method to `String.prototype` that... *(cont'd)* – T.J. Crowder Nov 01 '17 at 22:23
  • *(continuing)* ...returns it to us: `Object.defineProperty(String.prototype, "getObject", {value: function() { return this; });` (http://jsfiddle.net/tyfozkmp/) Note that that's in loose (non-strict) mode. If it were in strict mode, even though the string object would get created (at least in specification terms), we wouldn't see it as `this` because the *original* value (the primitive) is passed as `this` instead (`this` can be primitive in strict mode; not in loose mode). (This is handy for several reasons, not least to enable optimization in the JavaScript engine.) Fun, eh? :-) – T.J. Crowder Nov 01 '17 at 22:23
  • What the hell! even `a["bar"]` returns `undefined`, I thought it would return `"baz"`! Thanks for the explanation and sorry for the quite-late reply. Wouldn't it be more appropriate to allow such behavior in the first place (by throwing an error whenever you try to add a property to a string), are such expressions plain useless ? – doubleOrt Nov 05 '17 at 16:44
  • @Taurus: Do you know, I've never heard anyone suggest that, but it would make sense to me (in strict mode). :-) – T.J. Crowder Nov 05 '17 at 17:17