Arguments 對象

2018-06-16 15:17 更新

當(dāng)控制器進入到函數(shù)代碼的執(zhí)行環(huán)境時,將創(chuàng)建一個 arguments 對象,除非它作為標(biāo)識符 "arguments" 出現(xiàn)在該函數(shù)的形參列表中,或者是該函數(shù)代碼內(nèi)部的變量聲明標(biāo)識符或函數(shù)聲明標(biāo)識符。

 Arguments 對象通過調(diào)用抽象方法 CreateArgumentsObject 創(chuàng)建,調(diào)用時將以下參數(shù)傳入:func, names, args, env, strict。將要執(zhí)行的函數(shù)對象作為 func 參數(shù),將該函數(shù)的所有形參名加入一個 List 列表,作為 names 參數(shù),將所有傳給內(nèi)部方法 [[Call]] 的實際參數(shù),作為 args 參數(shù),將該函數(shù)代碼的環(huán)境變量作為 env 參數(shù),將該函數(shù)代碼是否為嚴(yán)格代碼作為strict 參數(shù)。當(dāng) CreateArgumentsObject 調(diào)用時,按照以下步驟執(zhí)行:

  1. 令 len 為參數(shù) args 的元素個數(shù)
  2. 令 obj 為一個新建的 ECMAScript 對象
  3. 按照 8.12 章節(jié)中的規(guī)范去設(shè)定 obj 對象的所有內(nèi)部方法
  4. 將 obj 對象的內(nèi)部屬性 [[Class]] 設(shè)置為 "Arguments"
  5. 令 Object 為標(biāo)準(zhǔn)的內(nèi)置對象的構(gòu)造函數(shù) (15.2.2)
  6. 將 obj 對象的內(nèi)部屬性 [[Prototype]] 設(shè)置為標(biāo)準(zhǔn)的內(nèi)置對象的原型對象
  7. 調(diào)用 obj 的內(nèi)部方法 [[DefineOwnProperty]],將 "length" 傳遞進去,屬性描述符為:{[[Value]]: len, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true},參數(shù)為 false
  8. 令 map 為表達式 new Object() 創(chuàng)建的對象,就是名為 Object 的標(biāo)準(zhǔn)的內(nèi)置構(gòu)造函數(shù)
  9. 令 mappedNames 為一個空的 List 列表
  10. 令 indx = len - 1
  11. 當(dāng) indx >= 0 的時候,重復(fù)此過程:令 val 為 args(維度從 0 開始的 list 列表)的第 indx 維度所在的元素調(diào)用 obj 的內(nèi)部方法 [[DefineOwnProperty]],將 ToString(indx) 傳遞進去,屬性描述符為:{[[Value]]: val, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true},參數(shù)為 false如果 indx 小于 names 的元素個數(shù),則令 name 為 names(維度從 0 開始的 list 列表)的第 indx 維度所在的元素如果 strict 值為 false,且 name 不是一個 mappedNames 元素,則將 name 添加到 mappedNames 列表中,作為它的一個元素令 g 為調(diào)用抽象操作 MakeArgGetter 的結(jié)果,其參數(shù)為 name 和 env令 p 為調(diào)用抽象操作 MakeArgSetter 的結(jié)果,其參數(shù)為 name 和 env調(diào)用 map 對象的內(nèi)部方法 [[DefineOwnProperty]],將 ToString(indx) 傳遞進去,屬性描述符為:{[[Set]]: p, [[Get]]: g, [[Configurable]]: true},參數(shù)為 false令 indx = indx - 1
  12. 如果 mappedNames 不為空,則將 obj 對象的內(nèi)部屬性 [[ParameterMap]] 設(shè)置為 map將 obj 對象的內(nèi)部方法 [[Get]], [[GetOwnProperty]], [[DefineOwnProperty]], [[Delete]] 按下面給出的定義進行設(shè)置。
  13. 如果 strict 值為 false,則調(diào)用 obj 對象的內(nèi)部方法 [[DefineOwnProperty]],將 "callee" 傳遞進去,屬性描述符為;{[[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true},參數(shù)為 false
  14. 否則,strict 值為 true,那么令 thrower 為 [[ThrowTypeError]] 函數(shù)對象 (13.2.3)調(diào)用 obj 對象的內(nèi)部方法 [[DefineOwnProperty]],將 "caller" 傳遞進去,屬性描述符為 :{[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},參數(shù)為 false調(diào)用 obj 對象的內(nèi)部方法 [[DefineOwnProperty]],將 "callee" 傳遞進去,屬性描述符為 :{[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},參數(shù)為 false
  15. 返回 obj

 抽象操作 MakeArgGetter 以字符串 name 和環(huán)境記錄 env 作為參數(shù)被調(diào)用時,會創(chuàng)建一個函數(shù)對象,當(dāng)執(zhí)行完后,會返回在 env 中綁定的 name 的值。執(zhí)行步驟如下:

  1. 令 body 為字符 "return ",name,";" 的連接字符串
  2. 返回一個按照 13.2 章節(jié)中描述的方式創(chuàng)建的函數(shù)對象,它不需要形參列表,以 body 作為它的 FunctionBody,以 env 作為它的 Scope,并且 Strict 值為 true

 抽象操作 MakeArgSetter 以字符串 name 和環(huán)境記錄 env 作為參數(shù)被調(diào)用時,會創(chuàng)建一個函數(shù)對象,當(dāng)執(zhí)行完后,會給在 env 中綁定的 name 設(shè)置一個值。執(zhí)行步驟如下:

  1. 令 param 為 name 和字符串 "_arg" 的連接字符串
  2. 令 body 為字符串 " = ;";將 替換為 name 的值,將 替換為 param 的值
  3. 返回一個按照 13.2 章節(jié)中描述的方式創(chuàng)建的函數(shù)對象,以一個只包含字符串 param 的 list 列表作為它的形參,以 body 作為它的函數(shù)體(FunctionBody),以 env 作為它的Scope,并且 Strict 值為 true

 當(dāng) arguments 對象的內(nèi)部方法 [[Get]] 在一個非嚴(yán)格模式下帶有形參的函數(shù)中,在一個屬性名為 P 的條件下被調(diào)用時,其執(zhí)行步驟如下:

  1. 令 map 為 arguments 對象的內(nèi)部屬性 [[ParameterMap]]
  2. 令 isMapped 為 map 對象的內(nèi)部方法 [[GetOwnPropery]] 傳入?yún)?shù) P 的執(zhí)行結(jié)果
  3. 如果 isMapped 值為 undefined,則令 v 為 arguments 對象的內(nèi)部默認的 [[Get]] 方法(8.12.3),傳入?yún)?shù) P 的執(zhí)行結(jié)果如果 P 為 "caller",且 v 為嚴(yán)格模式下的 Function 對象,則拋出一個 TypeError 的異常返回 v
  4. 否則,map 包含一個 P 的形參映射表返回 map 對象的內(nèi)部方法 [[Get]] 傳入?yún)?shù) P 的執(zhí)行結(jié)果

 當(dāng) arguments 對象的內(nèi)部方法 [[GetOwnProperty]] 在一個非嚴(yán)格模式下帶有形參的函數(shù)中,在一個屬性名為 P 的條件下被調(diào)用時,其執(zhí)行步驟如下:

  1. 令 desc 為 arguments 對象的內(nèi)部方法 [[GetOwnPropery]](8.12.1)傳入?yún)?shù) P 的執(zhí)行結(jié)果
  2. 如果 desc 為 undefined,返回 desc
  3. 令 map 為 arguments 對象內(nèi)部屬性 [[ParameterMap]] 的值
  4. 令 isMapped 為 map 對象的內(nèi)部方法 [[GetOwnPropery]] 傳入?yún)?shù) P 的執(zhí)行結(jié)果
  5. 如果 isMapped 的值不是 undefined,則將 desc 的值設(shè)置為 map 對象的內(nèi)部方法 [[Get]] 傳入?yún)?shù) P 的執(zhí)行結(jié)果
  6. 返回 desc

 當(dāng) arguments 對象的內(nèi)部方法 [[DefineOwnProperty]] 在一個非嚴(yán)格模式下帶有形參的函數(shù)中,在一個屬性名為 P,屬性描述符為 Desc,布爾標(biāo)志為 Throw 的條件下被調(diào)用時,其執(zhí)行步驟如下:

  1. 令 map 為 arguments 對象的內(nèi)部屬性 [[ParameterMap]] 的值
  2. 令 isMapped 為 map 對象的內(nèi)部方法 [[GetOwnPropery]] 傳入?yún)?shù) P 的執(zhí)行結(jié)果
  3. 令 allowed 為 arguments 對象的內(nèi)部方法 [[DefineOwnPropery]](8.12.9)傳入?yún)?shù) P,Desc,false 的執(zhí)行結(jié)果
  4. 如果 allowed 為 false,則如果 Throw 為 true,則拋出一個 TypeError 的異常,否則,返回 false
  5. 如果 isMapped 的值不為 undefined,則如果 IsAccessorDescriptor(Desc) 為 true,則調(diào)用 map 對象的內(nèi)部方法 [[Delete]],傳入 P 和 false 作為參數(shù)否則如果 Desc.[[Value]] 存在,則調(diào)用 map 對象的內(nèi)部方法 [[Put]],傳入 P,Desc.[[Value]] 和 Throw 作為參數(shù)如果 Desc.[[Writable]] 存在,且其值為 false,則調(diào)用 map 對象的內(nèi)部方法 [[Delete]],傳入 P 和 false 作為參數(shù)
  6. 返回 true

 當(dāng) arguments 對象的內(nèi)部方法 [[Delete]] 在一個非嚴(yán)格模式下帶有形參的函數(shù)中,在一個屬性名為 P,布爾標(biāo)志為 Throw 的條件下被調(diào)用時,其執(zhí)行步驟如下:

  1. 令 map 為 arguments 對象的內(nèi)部屬性 [[ParameterMap]] 的值
  2. 令 isMapped 為 map 對象的內(nèi)部方法 [[GetOwnPropery]] 傳入?yún)?shù) P 的執(zhí)行結(jié)果
  3. 令 result 為 arguments 對象的內(nèi)部方法 [[Delete]](8.12.7)傳入?yún)?shù) P 和 Throw 的執(zhí)行結(jié)果
  4. 如果 result 為 true,且 isMapped 不為 undefined,則調(diào)用 map 對象的內(nèi)部方法 [[Delete]],傳入 P 和 false 作為參數(shù)
  5. 返回 result

 非嚴(yán)格模式下的函數(shù),arguments 對象以數(shù)組索引(參見 15.4 的定義)作為數(shù)據(jù)屬性的命名,其數(shù)字名字的值少于對應(yīng)的函數(shù)對象初始時的形參數(shù)量,它們與綁定在該函數(shù)執(zhí)行環(huán)境中對應(yīng)的參數(shù)共享值。這意味著,改變該屬性將改變這些對應(yīng)的、綁定的參數(shù)的值,反之亦然。如果其中一個屬性被刪除然后再對其重定義,或者其中一個屬性在某個訪問器屬性內(nèi)部被更改,則這種對應(yīng)關(guān)系將被打破。嚴(yán)格模式下的函數(shù),arguments 對象的屬性值就是傳入該函數(shù)的實際參數(shù)的簡單拷貝,它們與形參之間的值不存在動態(tài)的聯(lián)動關(guān)系。

 ParameterMap 對象和它的屬性值被作為說明 arguments 對象對應(yīng)綁定參數(shù)的裝置。ParameterMap 對象和它的屬性值對象不能直接被 ECMAScript 代碼訪問。作為 ECMAScript 的實現(xiàn),不需要實際創(chuàng)建或使用這些對象去實現(xiàn)指定的語義。

 嚴(yán)格模式下函數(shù)的 Arguments 對象定義的非可配置的訪問器屬性,"caller" 和 "callee",在它們被訪問時,將拋出一個 TypeError 的異常。在非嚴(yán)格模式下,"callee" 屬性具有非常明確的意義,"caller" 屬性有一個歷史問題,它是否被提供,視為一個由實作環(huán)境決定的,在具體的 ECMAScript 實作進行擴展。在嚴(yán)格模式下對這些屬性的定義的出現(xiàn)是為了確保它們倆誰也不能在規(guī)范的 ECMAScript 實作中以任何方式被定義。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號