Разговор о области действия в JavaScript

интервью внешний интерфейс JavaScript функциональное программирование

После долгого изучения Javascript мне стыдно, что я до сих пор не обобщил весь объем.Сегодня я подытожу его:

Вовлеченный контент:

  1. глобальная область
  2. объем функции
  3. область действия блока
  4. лексический охват
  5. Динамическая область видимости Динамическая область видимости связана с механизмом этой ссылки.

Глобальный охват:

Область действия относится к сроку жизни переменной (область, в которой переменная содержит определенное значение).

Глобальная переменная:

Жизненный цикл будет существовать в рамках всей программы.

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

По умолчанию он модифицируется в JavaScript.

Глобальные переменные хоть и просты в использовании, но очень пугают, что признают все программисты.

Явно объявить:

объявление с ключевым словом var;

<script type="text/javascript">

    var testValue = 123;

    var testFunc = function () { console.log('just test') };

    /**---------全局变量会挂载到 window 对象上------------**/

    console.log(window.testFunc)		// ƒ () { console.log('just test') }

    console.log(window.testValue)		// 123
    
</script>

На самом деле, если функция, которую мы пишем, не инкапсулирована, она тоже будет глобальной переменной, а ее жизненный цикл — это глобальная область видимости;

Неявное объявление:

безобъявить ключевые словапеременная, JS по умолчанию объявит для вас глобальную переменную! ! !

<script type="text/javascript">

    function foo(value) {

      result = value + 1;	 // 没有用 var 修饰

      return result;
    };

    foo(123);				// 124
    
    console.log(window.result);			// 124 <=  挂在了 window全局对象上 
    
</script>

Теперь переменнаяresultмонтируется наwindowОбъект включен! ! !

Объем функций:

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


function bar() {
  var testValue = 'inner';
}

console.log(testValue);		// 报错:ReferenceError: testValue is not defined
Используйте return для доступа к переменным внутри функций:
function bar(value) {
  var testValue = 'inner';
  
  return testValue + value;
}

console.log(bar('fun'));		// "innerfun"

Функция похожа на фабрику, мы что-то вводим, она обрабатывает это внутри, а затем дает нам обработанный продукт;

Доступ к переменным внутри функций через замыкания:
function bar(value) {
  var testValue = 'inner';
  
  var rusult = testValue + value;
  
  function innser() {
     return rusult;
  };
  
  return innser();
}

console.log(bar('fun'));		// "innerfun"

Что касается замыканий, я не буду слишком много описывать в этой статье, потому что, если вы хотите описать замыкания, вам понадобится такая же длина, как и эта статья;

Немедленно выполнить функцию:

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

<script type="text/javascript">

    (function() {

      var testValue = 123;

      var testFunc = function () { console.log('just test'); };

    })();

    console.log(window.testValue);		// undefined
    
    console.log(window.testFunc);		// undefined
    
</script>

он может выполняться автоматически(function() { //... })()Содержимое пакета вполне может устранить влияние глобальных переменных;

Объем блока:

До ES6 не существовало понятия области действия блока. Если у вас есть опыт работы с C++ или Java, вы, вероятно, знакомы с областью видимости на уровне блоков;

for(var i = 0; i < 5; i++) {
  // ...
}

console.log(i)				// 5

Очевидно, что переменные, объявленные с ключевым словом var, вforПосле того, как цикл все еще сохраняется в этой области;

Это может иллюстрировать:for() { }Тем не менее в глобальной области видимости он не производит такого же эффекта закрытия, как область действия функции;

Если вы хотите достичьобласть действия блокаЗатем нам нужно использоватьletДекларация ключевого слова! ! !

for(let i = 0; i < 5; i++) {
  // ...
}

console.log(i)				// 报错:ReferenceError: i is not defined

существуетforПосле того, как цикл завершает выполнение, переменная i освобождается, ее больше нет! ! !

Существуют также области блочного уровня, которые могут быть сформированыconstКлючевые слова:

if (true) {
  const a = 'inner';
}

console.log(a);				// 报错:ReferenceError: a is not defined

letиconstключевое слово, условием для создания области на уровне блока является наличие{ }пакет:

{
  let a = 'inner';
}
  
if (true) {
   let b = 'inner'; 
}

var i = 0;

// ......

Не стоит недооценивать область действия на уровне блоков, она может многое сделать для вас, например:

Вот пример, распространенный в интервью:

for(var i = 0; i < 5; i++) {
  setTimeout(function() {
     console.log(i);			// 5 5 5 5 5
  }, 200);
};

Это почти обязательный вопрос для объема, и вы могли бы подумать, что такой результат странный, но это произошло;

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

Поскольку этот цикл оценивается как 5 до завершения обратного вызова, как нам вернуть его в нормальное состояние? ? ?

Решение 1: вызовите функцию, создайте область действия функции:

for(var i = 0; i < 5; i++) {
  abc(i);
};

function abc(i) {
  setTimeout(function() {
     console.log(i);			// 0 1 2 3 4 
  }, 200); 
}

Это эквивалентно созданию 5 функциональных областей для сохранения, нашего значения i;

Решение 2. Используйте функцию немедленного выполнения для создания области действия функции;

for(var i = 0; i < 5; i++) {
  (function(j) {
    setTimeout(function() {
      console.log(j);
    }, 200);
  })(i);
};

Принцип тот же, что и выше, за исключением того, что функция выполняется автоматически, а значение i сохраняется 5 раз;

Решение 3:letСоздать область блока

for(let i = 0; i < 5; i++) {
    setTimeout(function() {
      console.log(i);
    }, 200);
};

Лексическая область:

Лексическая область видимости относится к видимости переменной и аналоговому значению ее текстового представления («Функциональное программирование JavaScript»);

Звучит очень неясно, но это очень легко понять при анализе кода;

testValue = 'outer';

function afun() {
  var testValue = 'middle';
  
  console.log(testValue);		// "middle"
  
  function innerFun() {
    var testValue = 'inner';
    
    console.log(testValue);		// "inner"
  }
  
  return innerFun();
}

afun();

console.log(testValue);			// "outer"

Когда мы хотим использовать объявленную переменную: JS-движок всегда будет искать внешний домен из ближайшего домена;

Вот еще один практический пример:

var testValue = 'outer';

function foo() {
  console.log(testValue);		// "outer"
}

function bar() {
  var testValue = 'inner';
  
  foo();
}

bar();

Очевидно, когда JS-движок ищет эту переменную, он обнаруживает, что глобальная testValue ближе, что прямо противоположно динамической области видимости;

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

Динамический охват:

Одной из самых недооцененных и злоупотребляемых концепций в программировании является динамическая область действия ("Функциональное программирование JavaScript").

Единственное оставшееся место для применения динамической области видимости в JavaScript:thisцитаты, так что это большая дыра! ! ! ! !

Динамическая область, область действия основана на стеке вызовов, а не области, вложенной в код;

Вложенность области видимости имеет те же характеристики, что и лексическая область видимости.При поиске переменных всегда ищите ближайшую область видимости;

То же самое, лексическая область, пример 2, тот же код,еслиявляется динамической областью:

var testValue = 'outer';

function foo() {
  console.log(testValue);		// "inner"
}

function bar() {
  var testValue = 'inner';
  
  foo();
}

bar();

Конечно,JavaScriptКромеthisКроме того, все остальное ищется по лексическому объему! ! !

Зачем понимать динамическую область видимости? Потому что это заставит вас учиться лучшеthisЦитировать! ! !

Ссылки и благодарности:

  • «JavaScript, которого вы не знаете»
  • Функциональное программирование JavaScript

Прежде всего, благодаря авторам этих двух книг, я также могу хорошо обобщить объем своих собственных примеров и понимания;