Аргумент массива не расширяется в функции тега
Как правило, массивы в javascript являются расширяемыми, но это не так для массива, переданного в качестве первого аргумента функции тега:
let ary = [1,2,3];
console.log(Object.isExtensible(ary));
// returns true
function tag(ary, ...expressionResults)
{
console.log(Array.isArray(ary));
//returns true
console.log(Object.isExtensible(ary));
// returns false
}
tag`test`;
Где именно в спецификации этот массив считается нерасширяемым? Я даже не уверен, смотрю ли я в нужное место.
1 ответ
Вы искали в правильном месте. Связанная спецификация даже предлагает примечание относительно того, почему (emp. Mine):
ПРИМЕЧАНИЕ 2 Каждый TemplateLiteral в программном коде области связан с уникальным объектом шаблона, который используется при оценке тегированных шаблонов ( 12.2.9.6). Объекты шаблона замораживаются, и один и тот же объект шаблона используется каждый раз, когда оценивается конкретный помеченный шаблон.
Если вы хотите понять фактическое выполнение, сначала посмотрите на семантику выполнения тегированных шаблонов, указанную в разделе 12.3.7.1:
12.3.7.1 Семантика времени выполнения: оценка
MemberExpression: MemberExpression TemplateLiteral
[...]
- Вернуть? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall).
Если вы посмотрите на абстрактную операцию EvaluateCall:
12.3.4.2 Семантика времени выполнения: EvaluateCall (func, ref, arguments, tailPosition)
[...]
- Пусть argList будет ArgumentListEvaluation аргументов.
Таким образом, при вызове функции тега с литералом шаблона ArgumentListEvaluation из TemplateLiteral передается в качестве аргумента функции тега. Взгляните на ArgumentListEvaluation:
12.2.9.3 Семантика времени выполнения: ArgumentListEvaluation
TemplateLiteral: NoSubstitutionTemplate
[...]
- Пусть siteObj будет GetTemplateObject(templateLiteral).
Глядя на операцию GetTemplateObject, мы видим виновника:
12.2.9.4 Семантика времени выполнения: GetTemplateObject (templateLiteral)
[...]
- Выполните SetIntegrityLevel(шаблон"заморожен").
Где шаблон - массив, переданный функции тега. Мы видим, что он явно заморожен. Если вы хотите пойти на уровень глубже, посмотрите SetIntegrityLevel:
7.3.14 SetIntegrityLevel (O, уровень)
Абстрактная операция SetIntegrityLevel используется для исправления набора собственных свойств объекта. Эта абстрактная операция выполняет следующие шаги:
[...]
- Пусть статус будет? О.[[PreventExtensions]] ().
И, взглянув на [[PreventExtensions]] обычного объекта, мы видим, что вызывается операция OrdinaryPreventExtensions:
9.1.4.1 OrdinaryPreventExtensions (O)
Когда абстрактная операция OrdinaryPreventExtensions вызывается с Объектом O, предпринимаются следующие шаги:
- Установите для O.[[Extensible]] значение false.
- Верните истину.
Поэтому внутренний слот [[Extensible]] явно установлен на false.