Если повторное объявление с помощью var повлияет на существующую переменную - PullRequest
5 голосов
/ 03 октября 2019

const show1 = function(x, y = () => {x = 2; return x;}) {
    let x = 3;
    console.log(y());
    console.log(x);
};
show1();

const show2 = function(x, y = () => {x = 2; return x;}) {
    x = 3;
    console.log(y());
    console.log(x);
};
show2();

const show3 = function(x, y = () => {x = 2; return x;}) {
    var x = 3;
    console.log(y());
    console.log(x);
};
show3();

output

show1: Uncaught SyntaxError: Identifier 'x' has already been decalred;
show2: 2 2
show3: 2 3

Вопрос

Мне сообщили, что существует временная мертвая зона, где переменные параметров объявляются и инициализируются. См. https://exploringjs.com/es6/ch_variables.html#sec_parameters-as-variables. Итак, здесь есть две области действия: одна - область действия параметра, а другая - область действия функции.

  1. Из-за ошибки в show1 я подумал, что существует xпеременная уже объявлена ​​в этой функции.
  2. Согласно Переопределение переменной javascript . Повторное объявление ничего не сделает с xvar). Почему результаты show2 и show3 отличаются.

Я разместил здесь тот же вопрос Если переменные уже были объявлены в начале выполнения функции , которая была замаскированакак дубликат. Но я не смог найти ничего полезного для моих сомнений.

Ответы [ 2 ]

4 голосов
/ 03 октября 2019

show1 выдает ошибку, потому что переменные, объявленные с let или const , не могут иметь других переменных с таким же именем , инициализированных в этом блоке (будь то в списке аргументов или с const/ let / var).


Переменные, на которые ссылаются параметры по умолчанию, имеют нечетные правила области видимости. Каждый аргумент по существу создает другой блок, в котором может быть определено это имя аргумента. Так что

const show3 = function(x, y = () => { x = 2; return x; }) {

в некоторой степени похоже (простите псевдо-код):

const show3 = < function >{
  let x = firstArg;
  {
    let y = secondArg === undefined ? () => { x = 2; return x; } : secondArg;
    {
      // function body

Когда вы просто назначаете имени переменной в списке аргументов, этот аргумент будет перезаписан. Но когда вы используете синтаксис для инициализации новой переменной (с var), вы создаете другую привязку для этого имени переменной, которая видна только внутри тела функции:

const show3 = {
  let x = firstArg;
  {
    let y = secondArg === undefined ? () => { x = 2; return x; }
    // the x referenced in the above line references the outer x, the first argument
    {
      // function body

      // since "var x" is declared here, any references to "x" in this block
      // will only reference the inner x
      // but not the outer x
      var x = /* something */

Итак, ваш show2 переназначает параметр с именем x на 3 в первой строке тела функции. Напротив, show3 создает привязку переменной new с тем же именем x, а ссылка функции y на x ссылается на аргумент x, который отличается.

1 голос
/ 03 октября 2019

Why the results of show2 and show3 are different.

давайте оценим ваш код следующим образом

const show2 = function(x, y = () => {x.value = 2; return x;}) {
    x = {name: "from argument", value: 3};
    console.log(y());//{name: "from argument", value: 2}
    console.log(x);//{name: "from argument", value: 2}
};
show2();

const show3 = function(x, y = () => {if(!x){x = {name:"from function", value: -1}}x.value = 2; return x;}) {
    var x = {name: "from var", value: 3};
    console.log(y());//{name: "from function", value: 2}
    console.log(x);//{name: "from var", value: 3}
};
show3();

const show4 = function(x, y = () => {if(!x){x = {name:"from function", value: -1}}x.value = 2; return x;}) {
    var x = {name: "from var", value: 3};
    console.log(y());//{name: "from outside", value: 2}
    console.log(x);//{name: "from var", value: 3}
};
show4({name:"from outside", value: -1})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...