## Аб'ект `arguments` У зоне бачнасці любой функцыі JavaScript ёсць доступ да адмысловай пераменнай `arguments`. Гэтая пераменная утрымлівае спіс усіх аргументаў, што былі перададзеныя функцыі. > **Заўвага:** У выпадку, калі `arguments` ужо быў створаны ўнутры зоны бачнасці > функцыі праз выраз `var`, або з'яўляецца фармальным параметрам, > аб'ект `arguments` не будзе створаны. Аб'ект `arguments` **не з'яўляецца** спадкаемцам `Array`. Ён мае падабенствы з масівам, напрыклад уласцівасць `length`. Але ён не ўспадкоўвае `Array.prototype`, а ўяўляе з сябе `Object`. Таму **не**магчыма выклікаць стандартныя метады `push`, `pop` або `slice` у аб'екта `arguments`. Тым не менш, ітэрацыя з звычайным цыклам `for` працуе карэктна. Неабходна канвертаваць яго ў сапраўдны аб'ект `Array`, каб прымяніць стандартныя метады масіваў. ### Канвертацыя ў масіў Ніжэйпрыведезны код верне новы масіў, які будзе ўтрымліваць усе элементы аб'екта `arguments`. Array.prototype.slice.call(arguments); Такая канвертацыя **марудная**, яе **не рэкамендуецца** выкарыстоўваць у крытычных у плане прадукцыйнасці частках кода. ### Перадача `arguments` Ніжэй прадстаўлены рэкамендаваны спосаб перадачы аргументаў з адной функцыі ў іншую. function foo() { bar.apply(null, arguments); } function bar(a, b, c) { // тут робім што-небудзь } Яшчэ адзін прыём — гэта выкарыстанне `call` і `apply` разам, каб ператварыць метады, што выкарыстоўваюць значэнне `this` як і свае аргументы, у звычайныя функцыі, што выкарыстоўваюць толькі аргументы. function Person(first, last) { this.first = first; this.last = last; } Person.prototype.fullname = function(joiner, options) { options = options || { order: "western" }; var first = options.order === "western" ? this.first : this.last; var last = options.order === "western" ? this.last : this.first; return first + (joiner || " ") + last; }; // Ствараем незвязаную версію "fullname", што можа быць выкарыстана з любым // аб'ектам, які мае ўласцівасці 'first' і 'last', перададзеным у якасці // першага параметра. Гэтую абгортку не трэба будзе мяняць, калі колькасць або // парадак аргументаў fullname зменяцца. Person.fullname = function() { // Result: Person.prototype.fullname.call(this, joiner, ..., argN); return Function.call.apply(Person.prototype.fullname, arguments); }; var grace = new Person("Grace", "Hopper"); // 'Grace Hopper' grace.fullname(); // 'Turing, Alan' Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); ### Фармальныя параметры і індэксы аргументаў Аб'ект `arguments` стварае *гэтэр* і *сэтэр* як да кожнай са сваіх уласцівасцяў, так і да фармальных параметраў функцыі. У выніку змена значэння фармальнага параметра зменіць таксама адпаведную ўласцівасць аб'екта `arguments`, і наадварот. function foo(a, b, c) { arguments[0] = 2; a; // 2 b = 4; arguments[1]; // 4 var d = c; d = 9; c; // 3 } foo(1, 2, 3); ### Міфы і праўда аб прадукцыйнасці Адзінае, калі `arguments` не ствараецца, — гэта калі ёсць фармальны аргумент функцыі або пераменная ўнутры яе з такім іменем. Не важна, выкарыстоўваюцца яны ці не. Як *гэтэры*, так і *сэтэры* ствараюцца **заўсёды**, таму іх выкарыстоўванне не мае амаль ніякага ўплыву на прадукцыйнасць. > **Заўвага для ES5:** *гэтэры* і *сэтэры* не ствараюцца ў строгім рэжыме. Тым не менш, ёсць адна рэч, якая можа жахліва знізіць прадукцыйнасць у сучасных рухавіках JavaScript — гэта выкарыстанне `arguments.callee`. function foo() { arguments.callee; // робім што-небудзь з функцыяй foo arguments.callee.caller; // і з функцыяй, якая выклікала foo } function bigLoop() { for(var i = 0; i < 100000; i++) { foo(); // Звычайна ўстаўляецца... } } У вышэйпрыведзеным кодзе `foo` больш не можа быць [устаўлена][1], бо ёй трэба ведаць аб сабе і аб функцыі, што яе выклікала. Гэта не толькі знішчае павышэнне прадукцыйнасці, якое магло адбыцца дзякуючы ўстаўцы, але і парушае інкапсуляцыю, бо функцыя цяпер залежыць ад спецыфічнага кантэксту, які яе выклікае. Выкарыстоўванне `arguments.callee` або яго ўласцівасцяў **вельмі непажадана**. > **Заўвага для ES5:** У строгім рэжыме `arguments.callee` кіне памылку `TypeError`, > бо яго выкарыстанне аб'яўлена састарэлым. [1]: http://en.wikipedia.org/wiki/Inlining