Очистка концепции скрытых классов V8

Я прочитал несколько статей о скрытых классах V8. Однако у меня все еще есть несколько вопросов в голове:

Если, скажем, есть два объекта:

var a = { }
a.x = 5
a.y = 6

var b = { }
b.y = 7
b.x = 8

Они заканчивают тем же скрытым классом или разделяют только потому, что один отправился 0 + x + y, а другой 0 + y + x? Как я понял, они получают разные классы, но просто хочу убедиться, что я их получил.

Тогда мы имеем этот случай:

function Point(x, y) {
    this.x = x
    this.y = y
}
var a = new Point(7, 8)

var b = { }
b.x = 6
b.y = 8

var c = {
    x: 8,
    y: 9
}

var d = {
    y: 9,
    x: 80
}

У нас заканчивается тот же скрытый класс? Я мог догадаться, что a, b и c do, но d нет. Если для таких объектных выражений не выполняется некоторая сортировка (аналогично анализу краткой декларации массива для типа).

Наконец, мы имеем следующее:

function PointA(x, y) {
    this.x = x
    this.y = y
}
var a = new PointA(7, 8)

function PointB(x, y) {
    this.x = x
    this.y = y
}
var b = new PointB(7, 8)

Это похоже на второй случай. Эти объекты кажутся одинаковыми, за исключением того, что их происхождение (instanceof...) отличается. Однако существуют ли объекты с тем же скрытым классом?

Ответ 1

Если вы загружаете V8 и создаете отладочную версию, вы можете случайно передать эти объекты функции в бесконечную и распечатайте оптимизированную разборку и посмотрите, считаются ли они такими же классами.

В первом случае вы правы, что у них будут разные скрытые классы.


Во втором случае вы ошибаетесь, у вас будет 4 разных класса, поэтому ни один из них не разделяет класс.

Во-первых, поля, которые добавляются к объекту вне конструктора или литералу объекта, не будут храниться непосредственно на объект, но в массиве, внешнем по отношению к объекту. Итак, почему b будет иметь другой скрытый класс от всех.

Уникальный конструктор будет строить объекты уникального класса, поэтому a будет иметь разные скрытые классы от всех. Объект литералы имеют свойства в разном порядке, что в том же случае, что и в первом случае.

Однако объектные литералы с точно такой же компоновкой будут совместно использовать скрытый класс, поэтому, если бы мы добавили объект e:

var e = {
    x: 32,
    y: -15
};

Тогда c будет использовать один и тот же скрытый класс с e.


В третьем случае у них будут разные скрытые классы по той же причине, что и во втором случае, уникальные конструкторы строить объекты разных классов.


Вы также можете найти этот интересный https://codereview.stackexchange.com/a/28360/9258

Ответ 2

Вы можете легко проверить, используя оболочку отладки V8 d8.

// test1.js
var a = { }
a.x = 5
a.y = 6

var b = { }
b.y = 7
b.x = 8

print( %HaveSameMap( a, b ) ); 

Затем запустите

$ d8 --allow-natives-syntax test1.js

Вы получите ожидаемый результат:

false

Для второго примера:

//test2.js
function Point(x, y) {
    this.x = x
    this.y = y
}

var a = new Point(7, 8)

var b = { }
b.x = 6
b.y = 8

var c = {
    x: 8,
    y: 9
}

var d = {
    y: 9,
    x: 80
}

print( %HaveSameMap( a, b ) );
print( %HaveSameMap( b, c ) );
print( %HaveSameMap( b, d ) );
print( %HaveSameMap( c, d ) );

Все 4 объекта имеют разные скрытые классы:

$ d8 --allow-natives-syntax test2.js
false
false
false
false

И последнее, но не менее важное:

// test3.js
function PointA(x, y) {
    this.x = x
    this.y = y
}
var a = new PointA(7, 8)

function PointB(x, y) {
    this.x = x
    this.y = y
}
var b = new PointB(7, 8)
var c = new PointB(1,4)

print( %HaveSameMap( a, b ) );
print( %HaveSameMap( b, c ) );

a и b имеют разные скрытые классы, но b и c то же самое.

$ d8 --allow-natives-syntax test3.js
false
true