Это законный JavaScript? Передача аргументов в функцию и их изменение - PullRequest
12 голосов
/ 22 июня 2011

Это законно?И работает ли он во всех браузерах?

function func1(a, b, c) {
  //b == 2 here
  change_em(arguments);
  //b should equal 3 here
}

function change_em(args) {
  args[0] = 6;
  args[1]++;
  args[2] = [];
}

func1('foo', 2);

Если вам интересно, мне нужно настроить аргументы в функции.Макрос был бы идеальным, за исключением того, что у javascript его нет.Выполнение этого должным образом, то есть передача переменных в функцию, затем возвращение их в объект и последующее извлечение их в вызывающей программе, будет почти таким же количеством кода, как просто копирование / вставка функции-регулятора.

Ответы [ 5 ]

12 голосов
/ 22 июня 2011

Действителен в строгих режимах EcmaScript 3 и EcmaScript 5, но недопустим в строгом режиме EcmaScript 5.Он работает во всех современных браузерах и самых старых.Он не должен работать в строгом режиме, например при запуске в Firefox 5 с директивой "use strict".

Из раздела Спецификация EcmaScript 5 10.6.11.c.ii

10.6 Аргументы Объект

...

Если для параметра false задано значение false, а имя не является элементом mappedNames, тогда

  1. Добавитьname как элемент списка mappedNames.

  2. Пусть g будет результатом вызова абстрактной операции MakeArgGetter с аргументами name и env.

  3. Пусть p будет результатом вызова абстрактной операции MakeArgSetter с аргументами name и env.

  4. Вызвать внутренний метод [[DefineOwnProperty]] карты, передавая ToString (indx), дескриптор свойства {[[Set]]: p, [[Get]]: g, [[Configurable]]: true} и false в качестве аргументов.

В основном, arguments объект получает установщик для каждого индекса, так что присвоение arguments[i] изменяет значение именованного параметра в позиции i.В спецификации есть язык, который заставляет его работать наоборот.

Это должно работать в нестрогом режиме в любом интерпретаторе

(function (x) {
  alert("x=" + x + ", arguments[0]=" + arguments[0]);  // Both should be 0
  arguments[0] = 1;
  alert("x=" + x + ", arguments[0]=" + arguments[0]);  // both should be 1
  x = 2;
  alert("x=" + x + ", arguments[0]=" + arguments[0]);  // both should be 2
 })(0);

Но если вы запустите вышеописанное в Firefox 5 сстрогое использование директивы вы получаете другое поведение:

(function (x) {
  "use strict";

  alert("x=" + x + ", arguments[0]=" + arguments[0]);  // Both should be 0
  arguments[0] = 1;
  alert("x=" + x + ", arguments[0]=" + arguments[0]);  // x=0, arguments[0]=1
  x = 2;
  alert("x=" + x + ", arguments[0]=" + arguments[0]);  // x=2, arguments[0]=1 
 })(0);
1 голос
/ 22 июня 2011

arguments является массивоподобным объектом, но, тем не менее, объектом. Поэтому, когда вы передадите его в качестве параметра другой функции, он будет передан по ссылке. Таким образом, когда вы изменяете любые значения, они также изменяются в исходном arguments объекте. Так что это будет работать так, как вы предлагаете. Насколько я знаю, передача объектов по ссылке поддерживается во всех браузерах, однако в строгом режиме EcmaScript 5 индекс объекта именованных свойств больше не динамически сопоставляется с именованными формальными параметрами, поэтому это не будет работать.

0 голосов
/ 22 июня 2011

Поскольку c не было передано при вызове func1(), оно не будет включено в аргументы.Поэтому настройка args[2] = [] в change_em() также не будет устанавливать c в родительской функции.

0 голосов
/ 22 июня 2011

Да, где «все браузеры» - это разумный список современных браузеров с поддержкой Javascript.

0 голосов
/ 22 июня 2011

См. Редактирование ниже & ndash; это не относится к этому вопросу, но все еще верно: В JavaScript только сложные типы (объекты и массивы) передаются по ссылке. Примитивные типы (строка, число и логическое значение) передаются по значению; изменение параметра повлияет только на эту переменную в локальной функции.

var primitive = 1;
var complex = { prop: 1 };

function func1() {
    change(primitive, complex);
    // primitive == 1
    // complex == { prop: 2 }
}

function change(a,b) {
    a++;
    b.prop++;
}


Редактировать: Я пропустил, что вы передаете объект arguments. Быстрый тест дает те же результаты в Chrome 13, IE 9, Firefox 4 и Opera 10.62.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...