Изменение значения параметра функции JavaScript с помощью массива arguments не работает - PullRequest
0 голосов
/ 23 января 2019

Я изучаю JavaScript и очень озадачен массивом свойств arguments.

У меня есть функция, которая принимает один аргумент и возвращает его. Когда я передаю параметр и переназначаю его с помощью arguments[0] = value, он обновляет значение.

function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a(1)); //returns 2

Но когда я вызываю ту же функцию без параметров, она возвращает undefined.

function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a()); //returns undefined

Но даже если я передам undefined, значение также обновится.

function a(b) {
  arguments[0] = 2;
  return b;
}
console.log(a(undefined)); //returns 2

Я думал, что если вы не передадите параметр в функцию JavaScript, он автоматически создаст его и присвоит значение undefined, и после обновления оно должно отражать обновленное значение, верно?

Также a() и a(undefined) - это одно и то же, верно?

Ответы [ 6 ]

0 голосов
/ 23 января 2019

Присвоение указателям arguments изменит значение связанного аргумента (назовем его n -ым аргументом) только в том случае, если функция была вызвана как минимум с n аргументами.Числово-индексированные свойства объекта arguments - это, по сути, сеттеры (и геттеры):

http://es5.github.io/#x10.6

Курсивом ниже приведены мои комментарии о том, как этот процесс связанна вопрос:

(Позвольте) args (быть) фактические аргументы, переданные внутреннему методу [[Call]]

  1. Позвольте len будет количеством элементов в аргументах.

  2. Пусть indx = len - 1.

  3. Повторите, пока indx >= 0, (, поэтому приведенный ниже цикл не будет выполняться, если в функцию не переданы аргументы: )

( назначить объекту argumentsсоздается, здесь называется map: )

    1. Добавить name в качестве элемента списка mappedNames.
  • Пусть g будет результатом вызова абстрактной операции MakeArgGetter с аргументами name и env.
  • Пусть p будет результатом вызова абстрактной операции MakeArgSetter с аргументами name и env.
  • Вызвать внутренний метод [[DefineOwnProperty]] для map, передавая ToString (indx), дескриптор свойства {[[Set]]: p, [[Get]]: g, [[Настраиваемый]]: true} и false в качестве аргументов.

Таким образом, если функция вызывается без аргументов, не будетустановить на arguments[0], поэтому переназначение его не изменит параметр с индексом 0.

То же самое происходит и с другими индикаторами - если вы вызываете функцию с 1 параметром, но функция принимаетдва параметра, присвоение arguments[1] не изменит второй параметр, потому что arguments[1] не имеет установщика:

function fn(a, b) {
  arguments[1] = 'bar';
  console.log(b);
}
fn('foo');

То есть

a() и a(undefined) - это одно и то же, верно?

неслучай, потому что второе приводит к arguments объекту с установщиком и получателем по индексу 0, в то время как первый - нет.

0 голосов
/ 23 января 2019

Это неопределенное определение значения из спецификации javascript:

примитивное значение, используемое, когда переменной не присвоено значение.

поэтому, если вы не укажете тип возвращаемого значения функции, он вернет неопределенное значение.

так что () и (не определено) это не одно и то же. возврат undefined основан на том, определен тип возврата или нет.

для уточнения аналогичный_проблема

0 голосов
/ 23 января 2019

Если вы не предоставляете какой-либо параметр, тогда массив arguments имеет length, равный 0. Затем вы пытаетесь установить несуществующий элемент массива на 2, что приводит к возвращению неопределенного

Вы можете просто проверить это с помощью этого фрагмента:

function a(b){ 
    alert(arguments.length) // It will prompt 0 when calling a() and 1 when calling a(undefined)
    arguments[0] = 2; 
    return b; 
}
0 голосов
/ 23 января 2019

Насколько я понимаю, объект аргументов отслеживает только то, что передается в функцию.Поскольку вы изначально ничего не передавали, b не связан, и в этот момент arguments не «отслеживает» b.Затем вы присваиваете значение инициализированному, но пустому объекту в виде массива arguments и, наконец, возвращаете b, что не определено.

Чтобы углубиться в это далее:

Если aНестрогая функция не содержит параметров rest, default или destructured, тогда значения в объекте arguments изменяются синхронно со значениями переменных аргумента.См. Приведенный ниже код:

function func(a) { 
  arguments[0] = 99; // updating arguments[0] also updates a
  console.log(a);
}
func(10); // 99

и

function func(a) { 
  a = 99; // updating a also updates arguments[0]
  console.log(arguments[0]);
}
func(10); // 99

Если нестрогая функция содержит параметры rest, default или destructured, тогда значения вобъект arguments не отслеживает значения аргументов.Вместо этого они отражают аргументы, предоставленные при вызове функции:

function func(a = 55) { 
  arguments[0] = 99; // updating arguments[0] does not also update a
  console.log(a);
}
func(10); // 10

и

function func(a = 55) { 
  a = 99; // updating a does not also update arguments[0]
  console.log(arguments[0]);
}
func(10); // 10

и

// An untracked default parameter
function func(a = 55) { 
  console.log(arguments[0]);
}
func(); // undefined

Источник: MDN Web docs

0 голосов
/ 23 января 2019

это потому, что аргументы - это не массив, это объект с целочисленными индексированными ключами данных и длиной свойства. И если длина равна нулю, это значит, что у вас нет аргументов

function a(b) {
    arguments[0] = 2;
    console.log(arguments.length) 
    return b;
}
a(1); // length 1  returns 2
console.log(a());  // length 0  returns undefined
0 голосов
/ 23 января 2019

ECMA 262 9,0 2018 описывает это поведение в 9.4.4 Аргументы Экзотические объекты с

ПРИМЕЧАНИЕ 1:

Свойства данных с целочисленными индексами экзотического объекта аргументов, числовые значения имен которого меньше числа формальных параметров соответствующего объекта функции , первоначально разделяют свои значения с соответствующими привязками аргументов в функции контекст исполнения . Это означает, что изменение свойства изменяет соответствующее значение привязки аргумента и наоборот. Это соответствие нарушается, если такое свойство удаляется и затем переопределяется или если свойство изменяется на свойство доступа . Если объект arguments является обычным объектом, значения его свойств являются просто копией аргументов, переданных функции, и динамическая связь между значениями свойств и значениями формальных параметров отсутствует.

Короче говоря,

  • если в 'sloppy mode', то все аргументы отображаются на их именованные переменные, если длина соответствует данному параметру, или

  • если в 'strict mode', то привязка теряется после передачи аргументов.

Это доступно для чтения только в более старой версии ECMA 262 7.0 2016 . Это описывает это поведение в 9.4.4 Аргументы Экзотические объекты с

Примечание 1:

Для нестрогих функций целочисленные индексированные свойства данных объекта аргументов, числовые значения имен которых меньше, чем число формальных параметров соответствующего объекта функции, первоначально делят свои значения с соответствующими привязками аргументов в контексте выполнения функции. Это означает, что изменение свойства изменяет соответствующее значение привязки аргумента и наоборот. Это соответствие нарушается, если такое свойство удаляется, а затем переопределяется или если свойство изменяется на свойство доступа. Для функций строгого режима значения свойств объекта arguments являются просто копией аргументов, переданных функции, и динамическая связь между значениями свойств и значениями формальных параметров отсутствует.

...