Аргумент массива не расширяется в функции тега

Как правило, массивы в 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

[...]

  1. Вернуть? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall).

Если вы посмотрите на абстрактную операцию EvaluateCall:

12.3.4.2 Семантика времени выполнения: EvaluateCall (func, ref, arguments, tailPosition)

[...]

  1. Пусть argList будет ArgumentListEvaluation аргументов.

Таким образом, при вызове функции тега с литералом шаблона ArgumentListEvaluation из TemplateLiteral передается в качестве аргумента функции тега. Взгляните на ArgumentListEvaluation:

12.2.9.3 Семантика времени выполнения: ArgumentListEvaluation

TemplateLiteral: NoSubstitutionTemplate

[...]

  1. Пусть siteObj будет GetTemplateObject(templateLiteral).

Глядя на операцию GetTemplateObject, мы видим виновника:

12.2.9.4 Семантика времени выполнения: GetTemplateObject (templateLiteral)

[...]

  1. Выполните SetIntegrityLevel(шаблон"заморожен").

Где шаблон - массив, переданный функции тега. Мы видим, что он явно заморожен. Если вы хотите пойти на уровень глубже, посмотрите SetIntegrityLevel:

7.3.14 SetIntegrityLevel (O, уровень)

Абстрактная операция SetIntegrityLevel используется для исправления набора собственных свойств объекта. Эта абстрактная операция выполняет следующие шаги:

[...]

  1. Пусть статус будет? О.[[PreventExtensions]] ().

И, взглянув на [[PreventExtensions]] обычного объекта, мы видим, что вызывается операция OrdinaryPreventExtensions:

9.1.4.1 OrdinaryPreventExtensions (O)

Когда абстрактная операция OrdinaryPreventExtensions вызывается с Объектом O, предпринимаются следующие шаги:

  1. Установите для O.[[Extensible]] значение false.
  2. Верните истину.

Поэтому внутренний слот [[Extensible]] явно установлен на false.

Другие вопросы по тегам