當控制器進入到函數代碼的執(zhí)行環(huán)境時,將創(chuàng)建一個 arguments 對象,除非它作為標識符 "arguments" 出現在該函數的形參列表中,或者是該函數代碼內部的變量聲明標識符或函數聲明標識符。
Arguments 對象通過調用抽象方法 CreateArgumentsObject 創(chuàng)建,調用時將以下參數傳入:func, names, args, env, strict。將要執(zhí)行的函數對象作為 func 參數,將該函數的所有形參名加入一個 List 列表,作為 names 參數,將所有傳給內部方法 [[Call]] 的實際參數,作為 args 參數,將該函數代碼的環(huán)境變量作為 env 參數,將該函數代碼是否為嚴格代碼作為strict 參數。當 CreateArgumentsObject 調用時,按照以下步驟執(zhí)行:
- 令 len 為參數 args 的元素個數
- 令 obj 為一個新建的 ECMAScript 對象
- 按照 8.12 章節(jié)中的規(guī)范去設定 obj 對象的所有內部方法
- 將 obj 對象的內部屬性 [[Class]] 設置為 "Arguments"
- 令 Object 為標準的內置對象的構造函數 (15.2.2)
- 將 obj 對象的內部屬性 [[Prototype]] 設置為標準的內置對象的原型對象
- 調用 obj 的內部方法 [[DefineOwnProperty]],將 "length" 傳遞進去,屬性描述符為:{[[Value]]: len, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true},參數為 false
- 令 map 為表達式 new Object() 創(chuàng)建的對象,就是名為 Object 的標準的內置構造函數
- 令 mappedNames 為一個空的 List 列表
- 令 indx = len - 1
- 當 indx >= 0 的時候,重復此過程:令 val 為 args(維度從 0 開始的 list 列表)的第 indx 維度所在的元素調用 obj 的內部方法 [[DefineOwnProperty]],將 ToString(indx) 傳遞進去,屬性描述符為:{[[Value]]: val, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true},參數為 false如果 indx 小于 names 的元素個數,則令 name 為 names(維度從 0 開始的 list 列表)的第 indx 維度所在的元素如果 strict 值為 false,且 name 不是一個 mappedNames 元素,則將 name 添加到 mappedNames 列表中,作為它的一個元素令 g 為調用抽象操作 MakeArgGetter 的結果,其參數為 name 和 env令 p 為調用抽象操作 MakeArgSetter 的結果,其參數為 name 和 env調用 map 對象的內部方法 [[DefineOwnProperty]],將 ToString(indx) 傳遞進去,屬性描述符為:{[[Set]]: p, [[Get]]: g, [[Configurable]]: true},參數為 false令 indx = indx - 1
- 如果 mappedNames 不為空,則將 obj 對象的內部屬性 [[ParameterMap]] 設置為 map將 obj 對象的內部方法 [[Get]], [[GetOwnProperty]], [[DefineOwnProperty]], [[Delete]] 按下面給出的定義進行設置。
- 如果 strict 值為 false,則調用 obj 對象的內部方法 [[DefineOwnProperty]],將 "callee" 傳遞進去,屬性描述符為;{[[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true},參數為 false
- 否則,strict 值為 true,那么令 thrower 為 [[ThrowTypeError]] 函數對象 (13.2.3)調用 obj 對象的內部方法 [[DefineOwnProperty]],將 "caller" 傳遞進去,屬性描述符為 :{[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},參數為 false調用 obj 對象的內部方法 [[DefineOwnProperty]],將 "callee" 傳遞進去,屬性描述符為 :{[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},參數為 false
- 返回 obj
抽象操作 MakeArgGetter 以字符串 name 和環(huán)境記錄 env 作為參數被調用時,會創(chuàng)建一個函數對象,當執(zhí)行完后,會返回在 env 中綁定的 name 的值。執(zhí)行步驟如下:
- 令 body 為字符 "return ",name,";" 的連接字符串
- 返回一個按照 13.2 章節(jié)中描述的方式創(chuàng)建的函數對象,它不需要形參列表,以 body 作為它的 FunctionBody,以 env 作為它的 Scope,并且 Strict 值為 true
抽象操作 MakeArgSetter 以字符串 name 和環(huán)境記錄 env 作為參數被調用時,會創(chuàng)建一個函數對象,當執(zhí)行完后,會給在 env 中綁定的 name 設置一個值。執(zhí)行步驟如下:
- 令 param 為 name 和字符串 "_arg" 的連接字符串
- 令 body 為字符串 " = ;";將 替換為 name 的值,將 替換為 param 的值
- 返回一個按照 13.2 章節(jié)中描述的方式創(chuàng)建的函數對象,以一個只包含字符串 param 的 list 列表作為它的形參,以 body 作為它的函數體(FunctionBody),以 env 作為它的Scope,并且 Strict 值為 true
當 arguments 對象的內部方法 [[Get]] 在一個非嚴格模式下帶有形參的函數中,在一個屬性名為 P 的條件下被調用時,其執(zhí)行步驟如下:
- 令 map 為 arguments 對象的內部屬性 [[ParameterMap]]
- 令 isMapped 為 map 對象的內部方法 [[GetOwnPropery]] 傳入參數 P 的執(zhí)行結果
- 如果 isMapped 值為 undefined,則令 v 為 arguments 對象的內部默認的 [[Get]] 方法(8.12.3),傳入參數 P 的執(zhí)行結果如果 P 為 "caller",且 v 為嚴格模式下的 Function 對象,則拋出一個 TypeError 的異常返回 v
- 否則,map 包含一個 P 的形參映射表返回 map 對象的內部方法 [[Get]] 傳入參數 P 的執(zhí)行結果
當 arguments 對象的內部方法 [[GetOwnProperty]] 在一個非嚴格模式下帶有形參的函數中,在一個屬性名為 P 的條件下被調用時,其執(zhí)行步驟如下:
- 令 desc 為 arguments 對象的內部方法 [[GetOwnPropery]](8.12.1)傳入參數 P 的執(zhí)行結果
- 如果 desc 為 undefined,返回 desc
- 令 map 為 arguments 對象內部屬性 [[ParameterMap]] 的值
- 令 isMapped 為 map 對象的內部方法 [[GetOwnPropery]] 傳入參數 P 的執(zhí)行結果
- 如果 isMapped 的值不是 undefined,則將 desc 的值設置為 map 對象的內部方法 [[Get]] 傳入參數 P 的執(zhí)行結果
- 返回 desc
當 arguments 對象的內部方法 [[DefineOwnProperty]] 在一個非嚴格模式下帶有形參的函數中,在一個屬性名為 P,屬性描述符為 Desc,布爾標志為 Throw 的條件下被調用時,其執(zhí)行步驟如下:
- 令 map 為 arguments 對象的內部屬性 [[ParameterMap]] 的值
- 令 isMapped 為 map 對象的內部方法 [[GetOwnPropery]] 傳入參數 P 的執(zhí)行結果
- 令 allowed 為 arguments 對象的內部方法 [[DefineOwnPropery]](8.12.9)傳入參數 P,Desc,false 的執(zhí)行結果
- 如果 allowed 為 false,則如果 Throw 為 true,則拋出一個 TypeError 的異常,否則,返回 false
- 如果 isMapped 的值不為 undefined,則如果 IsAccessorDescriptor(Desc) 為 true,則調用 map 對象的內部方法 [[Delete]],傳入 P 和 false 作為參數否則如果 Desc.[[Value]] 存在,則調用 map 對象的內部方法 [[Put]],傳入 P,Desc.[[Value]] 和 Throw 作為參數如果 Desc.[[Writable]] 存在,且其值為 false,則調用 map 對象的內部方法 [[Delete]],傳入 P 和 false 作為參數
- 返回 true
當 arguments 對象的內部方法 [[Delete]] 在一個非嚴格模式下帶有形參的函數中,在一個屬性名為 P,布爾標志為 Throw 的條件下被調用時,其執(zhí)行步驟如下:
- 令 map 為 arguments 對象的內部屬性 [[ParameterMap]] 的值
- 令 isMapped 為 map 對象的內部方法 [[GetOwnPropery]] 傳入參數 P 的執(zhí)行結果
- 令 result 為 arguments 對象的內部方法 [[Delete]](8.12.7)傳入參數 P 和 Throw 的執(zhí)行結果
- 如果 result 為 true,且 isMapped 不為 undefined,則調用 map 對象的內部方法 [[Delete]],傳入 P 和 false 作為參數
- 返回 result
非嚴格模式下的函數,arguments 對象以數組索引(參見 15.4 的定義)作為數據屬性的命名,其數字名字的值少于對應的函數對象初始時的形參數量,它們與綁定在該函數執(zhí)行環(huán)境中對應的參數共享值。這意味著,改變該屬性將改變這些對應的、綁定的參數的值,反之亦然。如果其中一個屬性被刪除然后再對其重定義,或者其中一個屬性在某個訪問器屬性內部被更改,則這種對應關系將被打破。嚴格模式下的函數,arguments 對象的屬性值就是傳入該函數的實際參數的簡單拷貝,它們與形參之間的值不存在動態(tài)的聯(lián)動關系。
ParameterMap 對象和它的屬性值被作為說明 arguments 對象對應綁定參數的裝置。ParameterMap 對象和它的屬性值對象不能直接被 ECMAScript 代碼訪問。作為 ECMAScript 的實現,不需要實際創(chuàng)建或使用這些對象去實現指定的語義。
嚴格模式下函數的 Arguments 對象定義的非可配置的訪問器屬性,"caller" 和 "callee",在它們被訪問時,將拋出一個 TypeError 的異常。在非嚴格模式下,"callee" 屬性具有非常明確的意義,"caller" 屬性有一個歷史問題,它是否被提供,視為一個由實作環(huán)境決定的,在具體的 ECMAScript 實作進行擴展。在嚴格模式下對這些屬性的定義的出現是為了確保它們倆誰也不能在規(guī)范的 ECMAScript 實作中以任何方式被定義。
更多建議: