代码之家  ›  专栏  ›  技术社区  ›  Lonnie Best

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

  •  4
  • Lonnie Best  · 技术社区  · 7 年前

    通常,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`;

    在规范中,这个数组在哪里被认为是不可扩展的?我甚至不确定我是否在看右边 spot .

    1 回复  |  直到 7 年前
        1
  •  4
  •   Andrew Li    7 年前

    你找对了地方。链接的规范甚至提供了一个关于原因的注释(EMP。矿井):

    注释2 各 颞板的 在程序代码中 realm 与唯一的模板对象关联,该对象用于评估标记模板( 12.2.9.6 ) 模板对象被冻结 每次评估特定的标记模板时都使用相同的模板对象。

    如果您想了解实际的执行,请首先查看标记模板的运行时语义,它是在 Section 12.3.7.1 :

    12.3.7.1运行时语义:评估

    成员表达式:成员表达式模板

    [艾斯]

    1. 返回? EvaluateCall ( 塔芬克 , 塔格雷夫 ,请 颞板的 , 尾声 )

    如果你看一下抽象操作 评估所有 :

    12.3.4.2运行时语义:evaluateCall( 功能 , 裁判 , 争论 , 尾位 )

    [_]

    1. 让 阿尔卡特 是 ArgumentListEvaluation 属于 争论 .

    因此,当使用模板文本调用标记函数时,模板iteral的argumentListEvaluation将作为参数传递给标记函数。看看 论证列表评估 以下内容:

    12.2.9.3运行时语义:argumentListEvaluation

    模板:无替代模板

    [艾斯]

    1. 让 站点对象 是 GetTemplateObject ( 颞板的 )

    看手术 获取模板对象 我们看到了罪魁祸首:

    12.2.9.4运行时语义:getTemplateObject( 颞板的 )

    [艾斯]

    1. 表演 SetIntegrityLevel ( 模板 “冻结”。

    在哪里? 模板 是传递给标记函数的数组。我们看到它明显被冻结了。如果您想更深入一层,请参见 设置完整性级别 :

    7.3.14设置完整性级别( o ,请 水平 )

    抽象操作setIntegrityLevel用于修复对象自己的属性集。此抽象操作执行以下步骤:

    [艾斯]

    1. 让 地位 是吗? O型 .[[预防扩展]]()。

    再看看 [[PreventExtensions]] 对于一个普通物体,我们看到了这个操作 OrdinaryPreventExtensions 被称为:

    9.1.4.1常规预防性延期( o )

    当使用对象o调用抽象操作ordinaryPreventExtensions时,将执行以下步骤:

    1. 集合 o .[[可扩展]]至 假 .
    2. 返回 真 .

    因此,[[可扩展]]内部槽显式设置为假。