аргументы функции

function Foo(f) {
   var f = f;    
}

Здесь внутри функции переменная f является локальной по отношению к Foo (она имеет область действия функции), но почему переменная f в списке аргументов не конфликтует? Может быть, потому что он связан внутри объекта Foo.arguments?

В других языках мы не можем объявлять переменную-аргумент с тем же именем, что и локальная переменная.

Как разрешается эта двусмысленность имени? Или как вы ссылаетесь на каждую из двух отдельных переменных f позже в методе?


person xdevel2000    schedule 19.03.2009    source источник
comment
А в чем вопрос?   -  person Ionuț G. Stan    schedule 19.03.2009
comment
Подразумевается вопрос: как решается неоднозначность имени или как вы ссылаетесь на каждую из двух отдельных переменных «f» позже в методе.   -  person Joel Coehoorn    schedule 19.03.2009


Ответы (5)


JavaScript делает пару вещей, которые, очевидно, не являются интуитивными — тот, который вас интересует, называется «подъемом» — JS перемещает объявления var в начало функции, где они служат единственной цели резервирования этого имени переменной как локальная переменная в области видимости функции. Иногда это приводит к множеству странностей. Если имя переменной уже зарезервировано как локальная переменная (например, это аргумент), объявление var полностью удаляется.

Еще одна неинтуитивная часть JS — это то, как он работает с переменными-аргументами и объектом arguments (которые, как показал Бегемот, немного особенные). Однако это не обязательно то, что вас интересует - для вашего примера важно то, что аргументы также объявляют это имя переменной как локальное для функции.

Результатом всего этого является то, что когда у вас есть var f, а также имя аргумента f, `var f' отбрасывается, и ваш пример эквивалентен:

function Foo(f) {
   f = f;
}

Вы можете увидеть это на примере Бегемота, потому что:

function foo(f) {
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    var f = 10;
    console.log(f); // --> 10
    console.log(arguments); // --> [10] (!!!)
}

Эквивалентно:

function foo(f) {
    var f;
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    f = 10;
    console.log(f); // --> 10
    console.log(arguments); // --> [10] (!!!)
}

Эквивалентно:

function foo(f) {
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    f = 10;
    console.log(f); // --> 10
    console.log(arguments); // --> [10] (!!!)
}

Дополнительные сведения см. в разделе 10.1.3 — Создание переменных (внизу стр. 37) в ECMA-262, спецификация JS.

person Andrey Fedorov    schedule 19.03.2009
comment
hositing следует писать как hoisting - person Brian Wigginton; 27.09.2013

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

function foo(f) {
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    var f=10;
    console.log(f); // --> 10
    console.log(arguments); //even this is now array [10]
}
foo(11);
person TheHippo    schedule 19.03.2009
comment
на самом деле это неправильно: D при первом входе в журнал (f) он выдаст undefined, поскольку спецификация js поднимает все объявления var в начало функции (назначение остается в той же позиции) - person olliej; 20.03.2009
comment
@olliej: В этом случае f уже локально определено с помощью первого аргумента и фактически было установлено в 11 до выполнения функции из-за переданного значения. - person pimvdb; 15.02.2012

Как только вы объявляете новую переменную с тем же именем, что и у старой, она переопределяет ее, и вы не можете ссылаться на обе одновременно.

Вы должны либо изменить параметр, либо имя переменной.

person Seb    schedule 19.03.2009

здесь внутри функциональной переменной f является локальной для Foo (у нее есть область действия функции), но переменная f в списке аргументов, названная так же, почему она не конфликтует, может быть связана с тем, что она связана внутри Foo.arguments объект?

Нет, он не привязан к аргументам: arguments — это всего лишь массив позиционных значений аргументов, вы не можете получить из него «arguments.f».

Аргументы, переданные в функцию по имени, становятся локальными переменными. «var f» в функции с аргументом «f» является неявным.

Когда вы объявляете «var f» для переменной, которая уже является локальной, ничего не происходит. Ваш код идентичен:

function Foo(f)
{
    f = f;
}

В других языках мы не можем объявлять переменную-аргумент с тем же именем, что и локальная переменная.

В JavaScript до тех пор, пока есть одно использование «var x» в блоке области действия, любое использование «x» в этом блоке является локальным. Вы можете с радостью объявлять var для одной и той же переменной в одной и той же области снова и снова, но это ничего не делает.

person bobince    schedule 19.03.2009
comment
может быть областью действия... JS не имеет блока области видимости - person xdevel2000; 23.03.2009

В firefox я заметил, что объявление новой переменной не причиняет никакого вреда, как если бы для этого не было стамента

  <script type="text/javascript">

  function saymessage(f) {
    alert(f);
    var f = f;
    alert(f);
    alert(this.f);
  }
  </script>
</head>

<body >

  <!-- Insert Body Here -->
<button  id='link' textToShow="Hidden message text" onclick="saymessage('Hello World')">Click me </button>

</body>

Я получил "Hello World" в первом и втором предупреждениях и "undefined" в третьем.

person Jaime Garcia    schedule 19.03.2009
comment
да, потому что это привязано к объекту окна в этом контексте функции и не определено, потому что не существует никакой переменной, объявленной как window.f = ... - person xdevel2000; 19.03.2009