Объясните значения отладки для закрытия JavaScript - PullRequest
0 голосов
/ 25 октября 2018

Я хотел бы понять содержимое отладки во время выполнения следующего кода:

var z = 2;

var SQUAREPLUSOTHER = x => y => ((x*x) + y + z);

var x = 3;

console.log("SQUAREPLUSOTHER", SQUAREPLUSOTHER);

var squareoftwoplusother = (SQUAREPLUSOTHER)(x);

x = 4;
z = 4;
var result = squareoftwoplusother(5);
console.log("result", result);

Сейчас .... При вызове:

console.log("SQUAREPLUSOTHER", SQUAREPLUSOTHER);

отладкаясно показывает:

squareoftwoplusother: undefined
SQUAREPLUSOTHER: x=>...
x: 3
z: 2

при следующем вызове:

var SQUAREPLUSOTHER = x => y => ((x*x) + y + z);

, отладка показывает:

Local:
  x: 3
Closure
  z: 2

при следующем вызове:

x = 4;
z = 4;

отладка показывает:

squareoftwoplusother: y=>...
SQUAREPLUSOTHER: x=>...
x: 4
z: 4

при следующем вызове:

var result = squareoftwoplusother(5);

отладка показывает:

result: 18
squareoftwoplusother: y=>...
SQUAREPLUSOTHER: x=>...
Local:
  x: 5
Closure
  x: 3
Closure
  z: 4

и в финалевызывает отладочные шоу:

result: 18
squareoftwoplusother: y=>...
SQUAREPLUSOTHER: x=>...
x: 4
z: 4

теперь вопросы: сколько "замыканий"?Им принадлежит?(т.е. как объяснить ...)

Local:
  x: 5
Closure
  x: 3
Closure
  z: 4

Как управляется область действия переменных в javascript?Как иметь «окончательную» идею в терминах «контекста» или «как бы то ни было» о путанице замыкания :-)?

заранее спасибо

Ed

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Область действия

В вашем коде всего три области действия.Одна из них - это глобальная область видимости всех переменных, которые вы объявляете, а две другие находятся здесь:

 var SQUAREPLUSOTHER = x => y => ((x*x) + y + z);

Существует две области действия функции: одна содержит переменную x, а другая область действия содержит переменную y,Может быть легче увидеть, если вы замените функцию стрелки на function s:

 // global scope
 function SQUAREPLUSOTHER(x) {
   // function scope containing x
   return function(y) {
     // function scope containing y
     return (x*x) + y + z;
   };
 }

Как работает область видимости на самом деле довольно просто:

  • Every { запускает новую область видимости, а ее счетчик } закрывает ее, переменные, объявленные внутри нее с let и const (или var, но это немного сложнее), являются частью области действия.Если это область действия функции, то параметры (например, x и y) являются частью этой области.

  • Из кода вы можете получить доступ ко всем переменным, которыенаходятся в текущей области или в родительской области, если есть несколько с одним и тем же именем, вы получаете наиболее внутреннюю.Поэтому x внутри функции SQUAREPLUSOTHER ссылается на переменную области действия SQUAREPLUSOTHER, в то время как для кода вне ее x является глобальной переменной, и переменная функций недоступна.

Область действия переменной не изменяется во время выполнения, вы всегда можете непосредственно увидеть, какой области видимости переменной принадлежит tp, взглянув на окружающие { .. }.

Теперь разные переменные в разных областях должны содержать значения во время выполнения, вот где мы получаем:

запись среды

Когда вы вызываетеФункция JavaScript создает новый «EnvironmentRecord» (который похож на внутренний объект), который содержит все переменные вызываемой функции, например, в этом случае:

  function test(a) {
    let b;
  }

Затем, если вы вызываете эту функцию(test(1)) создается новая запись среды, которая содержит a и b.Теперь запускается код внутри функции, и в ней ищется каждая переменная.Если есть две функции, вложенные в другую, вызов внутренней функции создаст запись среды, которая содержит ссылку на внешнюю:

 function test(a) {
   function test2(b) {
   }

   test2(5);
 }

Теперь вызов test(1) создаст запись, где a1.Если механизм затем выполняет второй вызов (test2(5)), он создает другую запись, содержащую b, являющуюся 5, и которая содержит ссылку на запись, содержащую a.Теперь, если вы используете a внутри test2, движок будет искать его в текущей записи среды, не найдет его, а затем ищет в родительском месте, где он найдет a, являющийся 1.

closure

Обычно эти записи удаляются, когда выполнение достигает }, однако, если есть другая запись, получившая текущую запись в качестве родителя, она выигрывает 'удалитьОн будет существовать до тех пор, пока не будут удалены все дочерние записи, тогда он также удалит родительский элемент.Такое поведение (переменные живут дольше, поскольку к ним можно получить доступ из тела внутренних функций) называется закрытием.

0 голосов
/ 25 октября 2018

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

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

Здесь дается отличное объяснение http://dmitrysoshnikov.com/ecmascript/javascript-the-core/#activation-object

Я добавлю несколько скобок в ваш код, чтобы сделать это проще, и добавлю функцию самовызова, чтобы добавить уровень замыканий.

(() => {
  var z = 2;

  var SQUAREPLUSOTHER = (x) => {
    debugger;
    return (y) => {
      debugger;
      return (x * x) + y + z;
    }
  };

  var x = 3;

  console.log("SQUAREPLUSOTHER", SQUAREPLUSOTHER);

  var squareoftwoplusother = (SQUAREPLUSOTHER)(x);

  x = 4;
  z = 4;
  var result = squareoftwoplusother(5);
  console.log("result", result);
  debugger
})()

Приведенные ниже снимки экрана взяты из Chrome DevTools, который минимизирует замыкания, то есть он содержит только ссылки на то, что необходимо.В свое время все замыкания всегда были доступны, и вы можете доказать это, потому что они обнаружились на панели замыканий отладчиков.См. Javascript закрывает производительность для получения дополнительной информации

First breakpoint

Second Breakpoint

End of code

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...