В чем причина такого поведения?
function f(x) {
console.log(arguments[0]);
x = 42;
console.log(arguments[0]);
}
f(1);
// => 1
// => 42
Возможно, это была настоящая ошибка. Какой раздел спецификации ECMAScript определяет это поведение?
В чем причина такого поведения?
function f(x) {
console.log(arguments[0]);
x = 42;
console.log(arguments[0]);
}
f(1);
// => 1
// => 42
Возможно, это была настоящая ошибка. Какой раздел спецификации ECMAScript определяет это поведение?
Собственно, в строгом режиме это не происходит, как которое вы можете увидеть здесь.
Если вы прочитали раздел 10.6 стандарта ECMA, в частности Примечание 1, вы увидите:
Для функций нестрого режима индекс массива (определенный в 15.4) назвал свойства данных объекта аргументов числовые значения которых меньше числа формальных параметров соответствующего функционального объекта делиться своими значениями с соответствующими привязками аргументов в контексте выполнения функции. Это означает, что изменение свойство изменяет соответствующее значение привязки аргумента и наоборот. Это соответствие нарушается, если такое свойство удаляется, а затем переопределяется или изменяется свойство в свойство accessor. Для строгого режима функции, значения свойств объекта arguments являются просто копией аргументов, переданных функции, и динамическая связь между значениями свойств и формальными значениями параметров отсутствует.
Короче говоря, это говорит о том, что в нестрогом режиме названные функциональные параметры работают как псевдонимы для элементов в объекте arguments
. Таким образом, изменение значения именованного параметра изменит значение эквивалентного элемента arguments
и наоборот. Это не ошибка. Это ожидаемое поведение.
Как редакционная статья, вероятно, не стоит полагаться на это поведение, так как это может привести к очень запутанному коду. Кроме того, такой код, если он выполняется в строгом режиме, больше не будет работать.
Изменение x
отражается в arguments[0]
, потому что индексы arguments
могут быть getter/seters для сопоставления именованного аргумента. Это определяется в шаге 11.c.ii из 10.6:
Добавить имя как элемент списка mappedNames.
Пусть g - результат вызова абстрактной операции MakeArgGetter с именами аргументов и env.
Пусть p является результатом вызова абстрактной операции MakeArgSetter с именами аргументов и env.
Вызвать внутренний метод [[DefineOwnProperty]] для передачи карты ToString (indx), дескриптор свойства {[[Set]]: p, [[Get]]: g, [[Configurable]]: true} и false в качестве аргументов.
Как указано выше, для этого требуется, чтобы Строгий был false, и в этом случае вызывается f
со значением для x
f() // undefined, undefined (no argument, no getter/setter)
f(1) // 1, 42