Самовыполняющееся закрытие JS: что происходит, когда внутри IIFE есть конфликтующие объявления?

Я просматривал JavaScript allonge#six и пришел к этому примеру (короткие комментарии после каждой строки кода ):

((PI) => {             //1 - Outer - PI = 3.14 
   ((PI) => {})(100);   // 2 - IIFE (LOCAL)  PI = 100


  // ((PI) => PI)(100) // alternative1 = LOCAL PI = 100
 //  ((PI) => {return PI;})(100) // alternative2 - LOCAL PI = 100

  return (diameter) => diameter * PI;  // 3 - PI = 3.14
})(3.14)(2)

Во всех этих случаях аргумент, ограниченный для PI во внешней функции, передается непосредственно оператору return, игнорируя, таким образом, IIFE. Единственный способ скрыть аргумент «PI» — изменить оператор return на это:

((PI) => (diameter) => diameter * PI)(100)

Итак, первый вопрос. Есть ли другой способ скрыть аргумент PI (тот, который привязан к внешней функции), кроме замыкания в этом случае?

Кроме того, я запускал код через консоль разработчика Google построчно и дошел до точки кода, где значение PI внутри IIFE «перезаписывается» до 3,14, несмотря на то, что ранее оно было ограничено до 100. PI внутри IIFE перезаписывается на  3.14 НЕСМОТРЯ НА ОГРАНИЧЕНИЕ 100 ранее

Второй вопрос:

Что происходит с IIFE внутри после его выполнения, в какой момент его значение PI перезаписывается до 3,14?


person vzR    schedule 07.08.2016    source источник
comment
С ES6 у вас есть let, который позволяет вам объявлять переменную только для текущей области, поэтому вы можете иметь, скажем, переменную с именем x вне цикла for и другую переменную с именем x внутри цикла for без перекрытия двух.   -  person VLAZ    schedule 07.08.2016
comment
Какой конфликт? Какие ИИФЭ? Что вы хотите перезаписать? Что вы хотите затенить?   -  person Oriol    schedule 07.08.2016


Ответы (1)


Мне было трудно понять, о чем именно вы спрашивали. Поэтому я просто реорганизовал код и добавил свои собственные комментарии, чтобы попытаться прояснить ситуацию для себя и, надеюсь, ответить на часть ваших вопросов.

var a = (function a(PI) {
   // In this scope, PI = 3.14

   (function b(PI) {
     // PI = 100
   })(100);

  return function c(diameter) {
    // PI = 3.14, still in scope `a`
    // diameter = 2, passed in from second call
    return diameter * PI;
  };
});

a_result = a(3.14); // == c, with PI = 3.14
c_result = a_result(2); // c called with diameter = 2, PI = 3.14 from scope `a`

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

person Whothehellisthat    schedule 07.08.2016
comment
Извините, если я не был слишком ясен в своем первоначальном вопросе; один вопрос заключался в том, что произойдет с функцией b в этом случае? поскольку он выполняется автоматически, не должен ли он возвращать 100 в область действия a и, таким образом, скрывать все, что вы передаете в a_result? А другой был о том, можно ли скрыть параметр, переданный в (строку с a_result), помимо использования замыкания. - person vzR; 08.08.2016
comment
Нет, b вообще ничего не делает. В пределах b PI = 100. У него есть собственная область применения. Область доступна для всех областей, вложенных в нее, но эти вложенные области могут затенять переменные родительской области, создавая свои собственные. Таким образом, переменная PI в b на самом деле является совершенно новой переменной, доступной только из области видимости b. - person Whothehellisthat; 08.08.2016
comment
Если вы добавите var PI = 1; к c, то c не сможет видеть переменную PI области видимости a. Он увидит только свое собственное имя, потому что оно затенило это имя переменной. - person Whothehellisthat; 08.08.2016
comment
(Кстати, я включу все это в ответ, как только будут даны ответы на все ваши вопросы.) - person Whothehellisthat; 08.08.2016
comment
О, я понял, я думал, что функция b - будучи IIFE, приведет к созданию переменной, которая принимает имя параметра (в данном случае PI), но вы правы, она ничего не делает (даже если вы добавил бы возвращаемое значение). Но что тогда с ним происходит? И еще есть проблема с изображением, которое я добавил: в этом случае в b у вас будет значение 3,14 для PI, несмотря на то, что оно уже выполняется с ограниченным значением. Но большое спасибо, что очень хорошо прояснили часть вопроса - person vzR; 08.08.2016
comment
Ничего не происходит в результате b, потому что b ничего не сделал. То, что PI = 3,14 на изображении, просто вводит в заблуждение. Вероятно, он путается с PI в IIFE и областью вне его. Если вы console.log из b, он зарегистрирует 100. - person Whothehellisthat; 08.08.2016