Javascript 数组参数在标记函数中不可扩展

Javascript 数组参数在标记函数中不可扩展,javascript,ecmascript-6,tagged-templates,ecmascript-2018,Javascript,Ecmascript 6,Tagged Templates,Ecmascript 2018,通常,javascript中的数组是可扩展的,但对于作为标记函数的第一个参数传递的数组,情况并非如此: let ari=[1,2,3]; log(Object.isExtensible(ari)); //返回true 函数标记(ary,…表达式结果) { console.log(Array.isArray(ary)); //返回true log(Object.isExtensible(ari)); //返回false } 标签'test'您找对了位置。链接的规范甚至提供了一个关于原因的注释(e

通常,javascript中的数组是可扩展的,但对于作为标记函数的第一个参数传递的数组,情况并非如此:

let ari=[1,2,3];
log(Object.isExtensible(ari));
//返回true
函数标记(ary,…表达式结果)
{
console.log(Array.isArray(ary));
//返回true
log(Object.isExtensible(ari));
//返回false
}

标签'test'您找对了位置。链接的规范甚至提供了一个关于原因的注释(emp.mine):

注2的程序代码中的每个TemplateLiteral与用于评估标记模板()的唯一模板对象相关联模板对象被冻结,并且每次评估特定标记的模板时都使用相同的模板对象

如果要了解实际执行情况,请首先查看标记模板的运行时语义,这些语义在:

12.3.7.1运行时语义:评估 MemberExpression:MemberExpression TemplateLiteral

[……]

  • 返回?(tagFunc、tagRef、TemplateLiteral、tailCall)
  • 如果您看一下抽象操作:

    12.3.4.2运行时语义:EvaluateCall(func、ref、arguments、tailPosition) [……]

  • 让argList成为一组参数
  • 因此,当使用模板文本调用标记函数时,TemplateLiteral的ArgumentListValuation将作为参数传递给标记函数。看看:

    12.2.9.3运行时语义:ArgumentListValuation TemplateLiteral:NoSubstitutionTemplate

    [……]

  • 让siteObj成为(templateLiteral)
  • 看看这次行动,我们看到了罪魁祸首:

    12.2.9.4运行时语义:GetTemplateObject(templateLiteral) [……]

  • 执行(模板“冻结”)
  • 其中模板是传递给标记函数的数组。我们看到它被明确冻结了。如果您想更深一层,请参阅:

    7.3.14设置整体水平(O级) 抽象操作SetIntegrityLevel用于修复对象自身的属性集。此抽象操作执行以下步骤:

    [……]

  • 让地位成为现实吧?O.[预防扩展]]()
  • 看看一个普通的物体,我们看到这个操作叫做:

    9.1.4.1常规预防扩展(O) 使用对象O调用抽象操作OrdinaryPreventExtensions时,将执行以下步骤:

  • 将O.[Extensible]]设置为false
  • 返回真值

  • 因此[[Extensible]]内部插槽被显式设置为false。

    不确定规范中该部分的变量确切指的是什么,但是
    SetIntegrityLevel(someVar,“冻结”)。
    听起来像是冻结了对象,这将使其不可扩展(步骤12和14)。我不喜欢这个数组不可扩展。明白为什么了。我希望我有你的理解能力。你的阐述对我很有帮助。