(разработчик V8 здесь.)
что загружает "LdaTheHole" в аккумулятор? Может быть "TheHole"?
Да.
Что означает «TheHole»?
Как правильно догадывается ответ Марка, это внутренний страж, что означает «здесь нет значения». Причина этого не в производительности (или распределении ресурсов); необходимо получить правильное поведение в некоторых ситуациях.
Для примера на основе массива рассмотрите следующий код:
var a = [1, 2, 3]; // (1)
a.__proto__ = [11, 22, 33]; // (2)
delete a[1]; // (3)
console.log(a[1]); // (4)
Это выведет 22
, потому что a
будет концептуально есть «дыра» с индексом [1]
, и вы можете, так сказать, «увидеть ее прототип через эту дыру». (Вы можете создать ту же ситуацию, если замените строки (1) и (3) на var a = [1, , 3]
.) Если a
имеет прототип по умолчанию, то вместо delete a[1]
вы можете написать a[1] = undefined
, или вот что delete
можно было бы сделать под капотом, и результат был бы таким же. Но с пользовательским прототипом есть разница: если вы напишите a[1] = undefined
вместо строки (3), то строка (4) выведет undefined
. Нам нужно, чтобы «дырочный» страж различал guish, является ли элемент [1]
undefined
или отсутствует вообще.
Есть несколько других случаев, когда проводится различие между «нет значения» и «определенный, чтобы быть« неопределенным »» полезен или необходим, например, для «временной мертвой зоны» переменных области блока. Переменные старого типа var
неявно поднимают свои объявления, тогда как доступ к переменным нового стиля let
до их определения является ошибкой. Правильное поведение:
var a = 1; print(a); // 1
let b = 1; print(b); // 1
print(c); var c = 1; // undefined
print(d); let d = 1; // ReferenceError: Cannot access 'd' before initialization
print(e); // ReferenceError: e is not defined
Таким образом, оператор print
(который является просто примером; то же самое верно для многих других операций) должен выполнять три разные вещи в зависимости от окружающего кода. V8 выполняет это путем внутреннего преобразования строк в:
let c = undefined; print(c); c = 1;
let d = <TheHole>; print(d); d = 1;
Таким образом, когда переменная, к которой осуществляется доступ, имеет в качестве значения «дыру», система знает, что что-то не так, поэтому в данном случае, а не загружая значение переменной и передавая ее в функцию print
, он знает, что это должна быть переменная в области блока, доступ к которой осуществляется до ее определения, поэтому он выдает соответствующее сообщение об ошибке.
Если вы испытываете искушение поиграйте с этим, помните, что «дыра» - это просто внутренний страж. Он никогда не может «просочиться» до JavaScript. Из вашего кода невозможно проверить, что переменная или свойство в настоящее время имеют это значение. Это скрытая деталь реализации - движки могут делать вещи по-другому; Просто так получилось, что наличие внутреннего «дырочного» стража - достаточно элегантный и эффективный способ решения множества проблем, поэтому V8 решает сделать это таким образом.