0

As far as I know objects can be of any size so you never know how big an object going to be. So it was implemented as a reference type. Unlike any primitive type which size you know in advance.That's what this article says. But strings... from another article:

String : A set of “elements” of 16-bit unsigned integer values. Because string is not a fixed value, the variable assigned a string does not contain the string but the reference to it.

But how is string of a primitive type then?

9
  • It's the way the language is designed. Does it make a lot of sense? No, but it does not matter; there's nothing you can do about it. Commented Apr 21, 2022 at 17:55
  • Which other article has that quote? Commented Apr 21, 2022 at 17:57
  • I'm just curious. I want to know how things work under the hood Commented Apr 21, 2022 at 17:57
  • 2
    My impression is that the author provides a lot of information that works great in C but doesn't really apply to JavaScript. The tiny foot note ("This is an oversimplification and is not intended as a description of an actual JavaScript implementation.") falls a bit short. Commented Apr 21, 2022 at 17:58
  • 3
    JavaScript is a high level language, it doesn't make much sense to think in those terms. Those are implementation details that are only relevant in the language used to write the runtime engine (typically C). Commented Apr 21, 2022 at 18:07

1 Answer 1

3

That book you're reading is weird.

A primitive type has a fixed size in memory. For example, a number occupies eight bytes of memory, and a boolean value can be represented with only one bit. The number type is the largest of the primitive types. If each JavaScript variable reserves eight bytes of memory, the variable can directly hold any primitive value.

Reference types are another matter, however. Objects, for example, can be of any length -- they do not have a fixed size. The same is true of arrays: an array can have any number of elements. Similarly, a function can contain any amount of JavaScript code. Since these types do not have a fixed size, their values cannot be stored directly in the eight bytes of memory associated with each variable. Instead, the variable stores a reference to the value. Typically, this reference is some form of pointer or memory address. It is not the data value itself, but it tells the variable where to look to find the value.

And then the author goes on to explain how this causes different behaviour, as if that was an effect of the memory layout. But they've got that the wrong way round. The distinction should be:

  • a primitive type has plain, immutable values, that will be copied by value when being passed around.
  • a reference type - synonymous with "the object type" - has mutable objects as values, which have an identity (created when the object is instantiated) and can have arbitrary changeable properties. A variable never holds "an object" itself, but rather a reference to it, and it is this reference that is getting copied when you pass it around.

That (and "arrays and functions are objects") is the gist of the JavaScript value model. How this is implemented doesn't really matter - in fact it differs from engine to engine.

Now when you ask "Why string is a primitive?", the answer is "because strings are immutable values and don't have properties".

Sign up to request clarification or add additional context in comments.

11 Comments

another question. We have primitive type that stores value like this: variable => address of a memory cell -> primitive value. And reference type that works like this: variable => address of a memory cell -> pointer -> memory cell -> object. Is that right?
Different primitive types will have different representations in memory. Small integers, booleans, null and undefined might be stored in the 32 bits of the memory cell. Floating point values might be stored using a 32-bit pointer to a double value elsewhere in memory. Strings and bigints will certainly be stored as pointers to the memory allocated for their values.
No, no, this totally depends on the implementation - I wrote "might". In Google's V8, they found that using 32-bit memory cells (even on 64-bit architectures) leads to smaller memory usage (but there's other optimisations, e.g. there exist array representations with 64-bit cells). Other JS engines differ from this, there are engines that use 64-bit memory cells for everything. But all these implementation details don't matter. Booleans, numbers, strings, bigints: they are primitive types, and behave as specified for JavaScript.
No, bigints and numbers are primitive types, not reference types. That storing them in memory requires pointers on usual computer architectures is an implementation detail. Put otherwise: you cannot have a reference to a primitive value in JS, and you can only have a reference to an object in JS (in contrast to other programming languages). This is what defines the terms "primitive value" and "reference value" in JavaScript. That's why I think explaining them through memory representations, oh, even mentioning memory in the first place, is very misleading.
Oh I thought you came from C/C++ or something and want to concern yourself with the low-level details. But really you shouldn't, when programming JavaScript. Just think of a "memory cell" (like an object property, array element or a variable) being able to hold either a boolean, number, string, bigint etc. or a reference to an object. It's all the same kind of memory cell, and it can hold any kind of value.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.