Подтвердить что ты не робот

Является ли этот законный javascript? Передача аргументов функции и ее изменение

Является ли это законным? И работает ли она во всех браузерах?

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 его нет. Выполняя это правильно, т.е. Передавая переменные функции, затем возвращая их в объект, а затем извлекая их в вызывающем, будет почти такой же код, как и копирование/вставка функции регулятора.

4b9b3361

Ответ 1

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

Из спецификации EcmaScript 5 10.6.11.c.ii

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

...

Если strict является false и имя не является элементом сопоставленных имен, то

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

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

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

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

В принципе, объект 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);

Ответ 2

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

Ответ 3

См. править ниже – это не относится к этому вопросу, но по-прежнему остается в силе: в 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.

Ответ 4

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

Ответ 5

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