Очистка концепции скрытых классов 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