0

The MDN page on Array#slice states:

For strings, numbers and booleans (not String, Number and Boolean objects), slice copies the values into the new array. Changes to the string, number or boolean in one array do not affect the other array.

Surely string literals, being reference types (admittedly with a value semantic), are not copied. Instead a reference is copied?

Ben Aston
  • 53,718
  • 65
  • 205
  • 331
  • 2
    It literally says that strings are copied and not their reference and therefore not affected in the second sentence. – schrej Jun 05 '17 at 23:02
  • 1
    This comment is simply a restatement of my question. I am questioning MDN's correctness. If I am wrong, I'll accept a short explanation in an answer... – Ben Aston Jun 05 '17 at 23:23
  • 1
    I *think* engines would optimize that (by not actually copying values), it seems possible to do so as strings are immutable, it won't violate the semantics of `slice` function. I'm also surprised that the doc mentions that, as I would have expected strings to be *not copied*. Also, ran a quick test: build a big array of strings, take memory snapshot, then slice that array to produce another big one, take new memory snapshot, compare statistics, result: memory occupied by strings is almost identical between 2 snapshots. – Hugues M. Jun 05 '17 at 23:23

2 Answers2

2

String literals produce immutable primitive values. Those are not reference values.

That strings might be implemented with shared references to character arrays in JS engines is just that, an implementation detail. As you say yourself, strings do have value semantics in JS, and that's all what matters.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I thought they were both primitive and reference (albeit immutable) types inasmuch as passing 'foo' around doesnt actually copy the bytes in 'foo'. Maybe my terminology is wrong. – Ben Aston Jun 05 '17 at 23:26
  • That the bytes are (usually) not copied is an engine optimisation for strings. They are not *reference types*, as that term specifically has the meaning "mutable object" in JS. Strings are not mutable, you cannot change their properties or characters - which is what makes this optimisation possible in the first place. – Bergi Jun 05 '17 at 23:27
  • OK. They certainly aren't like 1 and true though! – Ben Aston Jun 05 '17 at 23:30
  • Alright, alright, there was a terminology mistake in the question... But I think it's worth having an idea of what actually happens when you slice a giant array of strings, is that awfully inefficient or is that a reasonable thing to do? I find it interesting to ask the question, and to observe that engines actually optimize that. – Hugues M. Jun 05 '17 at 23:30
  • 1
    What if I told you a secret and reveal that some numbers are implemented with references to boxed double-precision floating point numbers as well? :-O – Bergi Jun 05 '17 at 23:30
  • I suppose I only care what is in the spec. I haven't drilled into it yet to see what it says. I have read at least one book that claims strings are not value types in JS. – Ben Aston Jun 05 '17 at 23:31
  • 1
    @HuguesMoreau You could [ask that question](https://stackoverflow.com/questions/ask) for sure, but it would be a duplicate of [Do common JavaScript implementations use string interning?](https://stackoverflow.com/q/5276915/1048572) – Bergi Jun 05 '17 at 23:31
  • The MDN description remains incorrect though yeah? It is over-specifying the behavior, when in reality it is implemnentation dependent. And most implementations will copy a ref... – Ben Aston Jun 05 '17 at 23:33
  • 2
    @BenAston If you only care about the spec, use the term "*primitive*". There is no official distinction between "value types" and "reference types" in JS. Both objects and primitives are *values*. – Bergi Jun 05 '17 at 23:38
  • @Bergi Hmm I thought string interning usually applies to string literals found in code, not values fetched from network or created from scratch without using literals. Calling `slice` on such an array does not involve interning, does it? – Hugues M. Jun 05 '17 at 23:40
  • I don't see why interning would not apply here (not that I am an expert). Of course I accept everything @Bergi says. – Ben Aston Jun 05 '17 at 23:42
  • Sorry for the extended comment, but per my original question, and this answer: if the spec makes no value/reference distinction, then surely that means that you cannot say with certainty whether strings are "not reference values"? AFAICT from this exchange it is implementation dependent... so MDN should be corrected to match this reality. – Ben Aston Jun 05 '17 at 23:45
  • 1
    @HuguesMoreau No, [string interning](https://en.wikipedia.org/wiki/String_interning) does not apply only to constants (although code literals are an obvious and simple target). It works for any dynamically constructed immutable value (see also [hash consing](https://en.wikipedia.org/wiki/Hash_consing)) that is used in multiple locations - when it's deemed worth it by the engine. – Bergi Jun 05 '17 at 23:49
  • @BenAston I don't see where MDN is wrong. It neither says that strings are references or that they are not, it only calls them "values". And that's certainly fine. The value is copied. Whether the "contents of the value" need to be copied for that does not matter in the context of this documentation. – Bergi Jun 05 '17 at 23:50
  • 1
    OK. I can agree with that. But I think MDN is misleading. If I say 'the value of "foo" is copied into the array' then I immediately think that 3*16bits have been copied... when in reality this is very unlikely to have happened. – Ben Aston Jun 05 '17 at 23:55
  • @BenAston Yeah, but JS doesn't deal with bytes. It's a high-level language :-) In my ears, the value "foo" is *one* value. 1. That's all what counts… – Bergi Jun 06 '17 at 00:02
  • They're almost all high level. And most of them deal with bytes. If JS didnt deal with bytes then it wouldn't need binary manipulation operators. Probably philosophical. – Ben Aston Jun 06 '17 at 00:10
0

No, string literals are considered primitive types in JavaScript, just like numbers.

See MDN - Strings # Distinction between string primitives and String objects

nikulis
  • 124
  • 6