skip to Main Content

I saw an answer of a question it says

As a general rule, in JavaScript all values, all objects, and all of their properties are stored on the heap.

So i started searching and i found this page it says

JavaScript values in V8 are represented as objects and allocated on the V8 heap, no matter if they are objects, arrays, numbers or strings. This allows us to represent any value as a pointer to an object.

and from the book : Speaking JavaScript

Primitive Values

The following are all of the primitive values (or primitives for short):

  • Booleans: true, false (see “Booleans” on page 12)
  • Numbers: 1736, 1.351 (see “Numbers” on page 14)
  • Strings: ‘abc’, "abc" (see “Strings” on page 15)
  • Two “nonvalues”: undefined, null (see “undefined and null” on page 10)

Primitives have the following characteristics:

Compared by value

The “content” is compared:

3 === 3

true

'abc' === 'abc'

true

Always immutable

Properties can’t be changed, added, or removed:

var str = 'abc';
str.length = 1; // try to change property `length`
str.length
// ⇒ no effect
3
str.foo = 3; // try to create property `foo`
str.foo
// ⇒ no effect, unknown property
undefined

(Reading an unknown property always returns undefined.)

Objects

All nonprimitive values are objects. The most common kinds of objects are:

  • Plain objects, which can be created by object literals (see “Single Objects” on page 25):
{
  firstName: 'Jane',
  lastName: 'Doe'
}

The preceding object has two properties: the value of property firstName is ‘Jane’
and the value of property lastName is ‘Doe’.

  • Arrays, which can be created by array literals (see “Arrays” on page 28):
[ 'apple', 'banana', 'cherry' ]

The preceding array has three elements that can be accessed via numeric indices.
For example, the index of ‘apple’ is 0.

  • Regular expressions, which can be created by regular expression literals (see “Regular
    Expressions” on page 31):
/^a+b+$/

Objects have the following characteristics:

Compared by reference

Identities are compared; every value has its own identity:

{} === {}
false
// two different empty objects
var obj1 = {};
var obj2 = obj1;
obj1 === obj2
true

Mutable by default

You can normally freely change, add, and remove properties (see “Single Objects” on page 25):

var obj = {};
obj.foo = 123; // add property `foo`
obj.foo
123

So my qusetion : Engine must know the value is a primative or object to know which characteristics will be applied. V8 engine represents any value as a pointer to an object.

So How does the V8 engine know the diffrence between primitive and object ( both are references ) ?

I think that
the pointer (reference) has a part that contains the primitive value itself ( for example if the primitive value is "hello" the pointer (reference) will contain "hello" ) if this part is empty the V8 engine will know this pointer (reference) points to an object
or the pointer has a part and this part works like a flag and that part tells the V8 engine if this pointer (reference) points to an object or this pointer (reference) points to a primitive value

2

Answers


  1. The parser (v8) always tokenizes values as objects. It’s just that the primitives are instances of hidden classes (like proxies to their native classes) so they remain immutable to be always ready for nondynamic allocation (with permanent size).

    There’s actually no primitive value in javascript internally (at the v8 context). They’re all objects.

    The Primitive Value only happens at script context, not at execution time (v8 context). It’s the kind of declaration itself that will be parsed by the interpreter that will define how the object properties are defined in the v8 context.

    When a parse is successful, it constructs a parse tree, a rooted tree structure in which each node is a Parse Node. Each Parse Node is an instance of a symbol in the grammar; it represents a span of the source text that can be derived from that symbol. The root node of the parse tree, representing the whole of the source text, is an instance of the parse’s goal symbol. When a Parse Node is an instance of a nonterminal, it is also an instance of some production that has that nonterminal as its left-hand side. Moreover, it has zero or more children, one for each symbol on the production’s right-hand side: each child is a Parse Node that is an instance of the corresponding symbol.

    From https://262.ecma-international.org/15.0/index.html#sec-syntactic-grammar

    When you write a primitive declaration in the script, the engine will instance a sealed object with that value in the memory, instance which can’t be changed.

    So, internally, all primitives are stored as an object.

    Here’s an example:

    console.log('Is a primitive integer sealed?', Object.isSealed(0));
    console.log('Which is the primitive integer constructor?', 0 .constructor);
    console.log('Is `0 .constructor` the same as `Number`?', Object.is(0 .constructor, Number));
    console.log('Primitive integer prototype hierarchy:');
    
    let current = 0;
    let hierarchy = [current];
    
    while ( ( current = Object.getPrototypeOf(current) ) != null )
    {
      hierarchy.push( Object.getOwnPropertyDescriptors(current) );
    }
    
    console.log(hierarchy);
    Login or Signup to reply.
  2. How does the V8 engine know the difference between primitive and object?

    Each thing in memory begins with a "shape descriptor" (also known as "hidden class", a.k.a. "map"). For JavaScript objects, the shape descriptor in particular describes their properties, their prototype, their constructor, their extensibility, etc. But other things in memory, such as internally-used objects and the representations of JS primitives, also have "shape descriptors", which encode e.g. "this is a Number" or "this is a string".

    if the primitive value is "hello" the pointer (reference) will contain "hello"

    No. Think about it: that couldn’t work, because pointers have a fixed size, whereas strings can be very long.

    the pointer has a part and this part works like a flag and that part tells the V8 engine if this pointer (reference) points to an object or this pointer (reference) points to a primitive value

    No. Think about it: that couldn’t work, because there are far more differences in behavior than just this binary choice. For example, some objects are frozen, so you can’t add properties to them; some have properties that can’t be overwritten, or that invoke a setter when you assign a new value to them.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search