Какова область переменных в JavaScript?

какова область переменных в javascript? Имеют ли они ту же область внутри, что и вне функции? Или это вообще имеет значение? Кроме того, где хранятся переменные, если они определены глобально?

26 ответов


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

  1. переменная с глобальной областью

    // global scope
    var a = 1;
    
    function one() {
      alert(a); // alerts '1'
    }
    
  2. локальная область

    // global scope
    var a = 1;
    
    function two(a) { // passing (a) makes it local scope
      alert(a); // alerts the given argument, not the global value of '1'
    }
    
    // local scope again
    function three() {
      var a = 3;
      alert(a); // alerts '3'
    }
    
  3. средний: нет такой вещи, как область блока в В JavaScript (в ES5; ЕС6 вводит let)

    a.

    var a = 1;
    
    function four() {
      if (true) {
        var a = 4;
      }
    
      alert(a); // alerts '4', not the global value of '1'
    }
    

    b.

    var a = 1;
    
    function one() {
      if (true) {
        let a = 4;
      }
    
      alert(a); // alerts '1' because the 'let' keyword uses block scoping
    }
    
  4. средний: свойства объекта

    var a = 1;
    
    function Five() {
      this.a = 5;
    }
    
    alert(new Five().a); // alerts '5'
    
  5. дополнительно: закрытие

    var a = 1;
    
    var six = (function() {
      var a = 6;
    
      return function() {
        // JavaScript "closure" means I have access to 'a' in here,
        // because it is defined in the function in which I was defined.
        alert(a); // alerts '6'
      };
    })();
    
  6. дополнительно: прототип область разрешение

    var a = 1;
    
    function seven() {
      this.a = 7;
    }
    
    // [object].prototype.property loses to
    // [object].property in the lookup chain. For example...
    
    // Won't get reached, because 'a' is set in the constructor above.
    seven.prototype.a = -1;
    
    // Will get reached, even though 'b' is NOT set in the constructor.
    seven.prototype.b = 8;
    
    alert(new seven().a); // alerts '7'
    alert(new seven().b); // alerts '8'
    

  7. Глобальный+Локальный: очень сложный случай

    var x = 5;
    
    (function () {
        console.log(x);
        var x = 10;
        console.log(x); 
    })();
    

    это распечатает undefined и 10, а не 5 и 10 поскольку JavaScript всегда перемещает объявления переменных (а не инициализации) в верхнюю часть области, что делает код эквивалентным:

    var x = 5;
    
    (function () {
        var x;
        console.log(x);
        x = 10;
        console.log(x); 
    })();
    
  8. предложение Catch-область действия переменная

    var e = 5;
    console.log(e);
    try {
        throw 6;
    } catch (e) {
        console.log(e);
    }
    console.log(e);
    

    это распечатает 5, 6, 5. Внутри catch пункт e тени глобальных и локальных переменных. Но эта специальная область предназначена только для переменной catched. Если вы пишете var f; внутри предложения catch, то это точно так же, как если бы вы определили его до или после блока try-catch.


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

элемент в цепочке областей-это в основном карта с указателем на ее родительскую область.

при разрешении переменной javascript начинается с внутренней области и ищет наружу.


переменные, объявленные глобально, имеют глобальную область. Переменные, объявленные внутри функции, относятся к этой функции и теневым глобальным переменным с тем же именем.

(Я уверен, что есть много тонкостей, которые настоящие программисты JavaScript смогут указать в других ответах. В частности, я наткнулся на этой странице о том, что именно this значит в любое время. Надеюсь это более вводная ссылка достаточно, чтобы вы начали хотя.)


старая школа JavaScript

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

  1. Глобальный Масштаб переменные известны во всем приложении, с самого начала приложения (*)
  2. Функциональные Возможности переменные известны в пределах функции они были объявлены в начале функции (*)

я не буду подробно останавливаться на этом, так как уже есть много других ответов, объясняющих разницу.


Современный JavaScript

на самые последние спецификации JavaScript теперь также разрешите третью область:

  1. Блок Рамки переменные известны в пределах блок они объявлены в, с момента они объявлено вперед (**)

как создать переменные блока?

традиционно вы создаете свои переменные следующим образом:

var myVariable = "Some text";

переменные области блока создаются следующим образом:

let myVariable = "Some text";

так в чем разница между функциональной областью и областью блока?

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

// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here

function loop(arr) {
    // i IS known here, but undefined
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( var i = 0; i < arr.length; i++ ) {
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( let j = 0; j < arr.length; j++ ) {
        // i IS known here, and has a value
        // j IS known here, and has a value
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here
}

loop([1,2,3,4]);

for( var k = 0; k < arr.length; k++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here
};

for( let l = 0; l < arr.length; l++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS known here, and has a value
};

loop([1,2,3,4]);

// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here

здесь мы видим, что наша переменная j известен только в первом цикле for, но не до и после. Еще, наши переменной i известно во всей функции.

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


безопасно ли использовать переменные области блока сегодня?

ли или не безопасно использовать сегодня, зависит от вашей окружающей среды:

  • если вы пишете серверный код JavaScript (узел.js), вы можете смело использовать let заявление.

  • если вы пишете клиентский код JavaScript и используете транспилер (например,Трейсер), вы можете смело использовать let оператор, однако ваш код, вероятно, будет чем угодно, но не оптимальным по производительности.

  • если вы пишете клиентский JavaScript-код и не используете транспилер, вам необходимо рассмотреть поддержку браузера.

    сегодня, 23 февраля 2016, это некоторые браузеры, которые либо не поддерживают let или только частичная поддержка :

    • Internet explorer 10 и ниже (без поддержки)
    • Firefox 43 и ниже (без поддержки)
    • сафари 9 и ниже (без поддержки)
    • Opera Mini 8 и ниже (без поддержки)
    • браузер Android 4 и ниже (без поддержки)
    • Опера 36 и ниже (частичное поддержка)
    • Chome 51 и ниже (частичная поддержка)

enter image description here


как отслеживать поддержку браузера

для обновленного обзора того, какие браузеры поддерживают let заявление во время чтения этого ответа см. этой Can I Use страница.


(*) во всем мире и функционально переменные можно инициализировать и использовать до их объявления, потому что переменные JavaScript подняли. это означает, что объявления всегда находятся в верхней части области.

(**) переменные области блока не поднимаются


вот пример:

<script>

var globalVariable = 7; //==window.globalVariable

function aGlobal( param ) { //==window.aGlobal(); 
                            //param is only accessible in this function
  var scopedToFunction = {
    //can't be accessed outside of this function

    nested : 3 //accessible by: scopedToFunction.nested
  };

  anotherGlobal = {
    //global because there's no `var`
  }; 

}

</script>

вы захотите исследовать замыкания и как их использовать, чтобы сделать частные члены.


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

вот хорошая статья на эту тему.


в "Javascript 1.7" (расширение Mozilla на Javascript) можно также объявить переменные области блока с let сообщении:

 var a = 4;
 let (a = 3) {
   alert(a); // 3
 }
 alert(a);   // 4

идея определения области в JavaScript при первоначальном проектировании Брендан Айх С HyperCard скриптовый язык HyperTalk.

на этом языке, дисплеи были сделаны похожими на стопки каталожных карточек. Там была мастер-карта, называемая фоном. Она была прозрачной и видна как нижняя карта. Любой контент на этой базовой карте был разделен с картами, размещенными поверх нее. Каждая карта, помещенная сверху, имела свой собственный контент, который имел приоритет над предыдущей картой, но при желании имел доступ к предыдущим картам.

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

эта привязка будет указывать на объект-контейнер. Иногда области или контексты выполнения изменяются без изменения содержащего объекта, например в объявленной функции, где содержащее объект может быть window или функцию конструктора.

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

Так что это техническое объяснение. На практике, важно помнить, что в JavaScript

  • области технически являются "контекстами выполнения"
  • контексты образуют стек сред, где переменные сохраняются
  • верхняя часть стека имеет приоритет (нижняя часть является глобальным контекстом)
  • каждая функция создает контекст выполнения (но не всегда новое это обязательным)

применяя это к одному из предыдущих примеров (5. "Закрытие") на этой странице можно следить за стеком контекстов выполнения. В этом примере в стеке есть три контекста. Они определяются внешним контекстом, контекстом в непосредственном вызывается функция, вызываемая var six, и контекст в возвращаемой функции внутри немедленно вызываемой функции var six.

я) внешний контекст. Он имеет переменную среду a = 1
ii) контекст IIFE, он имеет лексическую среду a = 1, но переменную среду a = 6, которая имеет приоритет в стеке
iii) возвращаемый контекст функции, он имеет лексическую среду a = 6, и это значение, указанное в предупреждении при вызове.

enter image description here


1) существует глобальная область, область функций и области with и catch. В общем случае для переменных -- операторы with и catch не добавляют имена к своим блокам.

2) области вложены функциями полностью в глобальную область.

3) решаются через цепочку прототипов. Оператор with вводит имена свойств объекта в лексическую область, определенную блоком with.

изменить: ECMAAScript 6 (Harmony) предназначен для поддержки let, и я знаю, что chrome позволяет флаг "harmony", поэтому, возможно, он поддерживает его..

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

EDIT: основываясь на указании Бенджамина из операторов with и catch в комментариях, я отредактировал сообщение и добавил больше. Операторы with и catch вводят переменные в свои соответствующие блоки, и это и объем блока. Эти переменные сглаживаются по свойствам передаваемых в них объектов.

 //chrome (v8)

 var a = { 'test1':'test1val' }
 test1   // error not defined
 with (a) { var test1 = 'replaced' }
 test1   // undefined
 a       // a.test1 = 'replaced'

EDIT: уточняющий пример:

test1 ограничен блоком with, но имеет псевдоним a.тест1. 'Var test1' создает новую переменную test1 в верхнем лексическом контексте (function или global), если только она не является свойством a -- which it is.

Yikes! Будьте осторожны с использованием 'with' -- так же, как var является noop, если переменная уже определена в функции это также noop относительно имен, импортированных из объекта! Немного внимания к имени, которое уже определено, сделало бы это намного безопаснее. Я лично никогда не буду использовать из-за этого.


Я обнаружил, что многие люди, новички в JavaScript, с трудом понимают, что наследование доступно по умолчанию на языке, и что область функции является единственной областью. В конце прошлого года я продлил контракт с красавицей по имени Джспретти. Область функции цвета объектов в коде и всегда связывает цвет со всеми переменными, объявленными в этой области. Закрытие визуально демонстрируется, когда переменная с цветом из одной области используется в другой масштаб.

использовать в:

смотрите демо по адресу:

Просмотр кода at:

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


JavaScript имеет только два типа области:

  1. Глобальный Масштаб : Global - это не что иное, как область уровня окна.Здесь переменная присутствует во всем приложении.
  2. Функциональные Возможности : переменная, объявленная в функции с var ключевое слово имеет функциональную область.

всякий раз, когда вызывается функция, создается объект переменной области (и включается в цепочку областей), за которым следует переменные в JavaScript.

        a = "global";
         function outer(){ 
              b = "local";
              console.log(a+b); //"globallocal"
         }
outer();

объем услуги -->

  1. окне уровень - a и outer функция на верхнем уровне в цепи объема.
  2. когда внешняя функция называется новый variable scope object(и включено в цепочку областей) добавлено с переменной b внутри него.

теперь, когда переменная a требуется, чтобы он сначала искал ближайшую область переменной, и если переменная не существует, то она перемещается к следующему объекту переменной scope-цепь.что в данном случае является оконным уровнем.


чтобы добавить к другим ответам, область поиска - это список всех объявленных идентификаторов (переменных) и обеспечивает строгий набор правил о том, как они доступны для текущего исполняемого кода. Этот поиск может быть для целей присвоения переменной, которая является ссылкой LHS (lefthand-side), или для целей извлечения ее значения, которое является ссылкой RHS (righthand-side). Эти запросы-это то, что движок JavaScript делает внутри, когда он компиляция и выполнение кода.

таким образом, с этой точки зрения, я думаю, что картина поможет, что я нашел в области и закрытия электронной книги Кайла Симпсона:

image

цитата из его книги:

здание представляет собой набор правил вложенной области нашей программы. Первый этаж здания представляет ваш текущий объем выполнения, где бы ты ни был. Верхний уровень здания-глобальный. Вы решаете ссылки LHS и RHS, глядя на свой текущий этаж, а если не найдете, поднимитесь на лифте на следующий этаж., смотрю туда, потом на следующий и так далее. Как только вы доберетесь до верхнего этажа (глобальная область), вы либо найдете то, что ищете, либо вы не надо. Но ты все равно должен остановиться.

одна вещь, которую стоит упомянуть, "Поиск области останавливается, как только он находит первое совпадение".

эта идея "уровней области" объясняет почему "это" можно изменить с помощью вновь созданной области, если она просматривается во вложенной функции. Вот ссылка, которая входит во все эти детали,все, что вы хотели знать о javascript scope


запустить код. надеюсь, это даст представление о scoping

Name = 'global data';
document.Name = 'current document data';
(function(window,document){
var Name = 'local data';
var myObj = {
    Name: 'object data',
    f: function(){
        alert(this.Name);
    }
};

myObj.newFun = function(){
    alert(this.Name);
}

function testFun(){
    alert("Window Scope : " + window.Name + 
          "\nLocal Scope : " + Name + 
          "\nObject Scope : " + this.Name + 
          "\nCurrent document Scope : " + document.Name
         );
}


testFun.call(myObj);
})(window,document);

Глобальные Масштабы :

глобальные переменные точно такие же, как глобальные звезды (Джеки Чан, Нельсон Мандела). Вы можете получить к ним доступ (получить или установить значение), из любой части вашего приложения. Глобальные функции подобны глобальным событиям (Новый Год, Рождество). Вы можете выполнить (вызвать) их из любой части приложения.

//global variable
var a = 2;

//global function
function b(){
   console.log(a);  //access global variable
}

Локальный Объем :

если вы находитесь в США, вы можете знать Ким Кардашьян, печально известную знаменитость ( она каким-то образом удается сделать таблоиды). Но люди за пределами США ее не узнают. Она местная звезда, привязанная к своей территории.

локальные переменные похожи на локальные звезды. Вы можете получить к ним доступ (получить или установить значение) только внутри области. Локальная функция похожа на локальные события - вы можете выполнять только (праздновать) внутри этой области. Если вы хотите получить к ним доступ из-за пределов области, вы получите ссылку ошибка

function b(){
   var d = 21; //local variable
   console.log(d);

   function dog(){  console.log(a); }
     dog(); //execute local function
}

 console.log(d); //ReferenceError: dddddd is not defined    

проверьте эту статью для глубокого понимания объем


существует почти только два типа областей JavaScript:

  • область каждого объявления var связана с наиболее непосредственно заключительной функцией
  • если нет заключительной функции для объявления var, это глобальная область

таким образом, любые блоки, кроме функций, не создают новую область. Это объясняет, почему for-loops перезаписывают внешние переменные области:

var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5

использование функций вместо этого:

var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10

в первом примере не было области блока, поэтому первоначально объявленные переменные были перезаписаны. Во втором примере из-за функции появилась новая область, поэтому первоначально объявленные переменные были затенены, а не перезаписаны.

Это почти все, что вам нужно знать с точки зрения области JavaScript, кроме:

  • try / catch вводит новую область только для самой переменной исключения, другие переменные не имеют новых объем
  • with-clause по-видимому, является еще одним исключением, но использование with-clause очень не рекомендуется (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with)

таким образом, вы можете видеть, что область JavaScript на самом деле чрезвычайно проста, хотя и не всегда интуитивно понятна. Несколько вещей, чтобы быть в курсе:

  • объявления var поднимаются в верхнюю часть области. Это означает, что независимо от того, где происходит объявление var, для компилятора это как если бы сам var происходил вверху
  • несколько объявлений var в одной области объединяются

так этот код:

var i = 1;
function abc() {
  i = 2;
  var i = 3;
}
console.log(i);     // outputs 1

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

var i = 1;
function abc() {
  var i;     // var declaration moved to the top of the scope
  i = 2;
  i = 3;     // the assignment stays where it is
}
console.log(i);

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


современный Js, ES6+,'const' и 'let'

вы должны использовать область видимости блоков для каждой переменной, которую вы создаете, как и большинство других основных языков. var и устаревшего. Это делает ваш код более безопасным и ремонтопригодным.

const следует использовать для 95% случаев. Это делает его таким переменным ссылка не можешь изменить. Свойства узлов Array, object и DOM могут изменяться и, вероятно, должны быть const.

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

область блока означает, что переменная будет доступна только в скобках, в которых она объявлена. Это распространяется на внутренние области, включая анонимные функции, созданные в пределах области.


в JS есть только области функций. Не блокируйте прицелы! Вы также можете видеть, что поднимается.

var global_variable = "global_variable";
var hoisting_variable = "global_hoist";

// Global variables printed
console.log("global_scope: - global_variable: " + global_variable);
console.log("global_scope: - hoisting_variable: " + hoisting_variable);

if (true) {
    // The variable block will be global, on true condition.
    var block = "block";
}
console.log("global_scope: - block: " + block);

function local_function() {
    var local_variable = "local_variable";
    console.log("local_scope: - local_variable: " + local_variable);
    console.log("local_scope: - global_variable: " + global_variable);
    console.log("local_scope: - block: " + block);
    // The hoisting_variable is undefined at the moment.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);

    var hoisting_variable = "local_hoist";
    // The hoisting_variable is now set as a local one.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);
}

local_function();

// No variable in a separate function is visible into the global scope.
console.log("global_scope: - local_variable: " + local_variable);

каждый фрагмент кода JavaScript (глобальный код или функции) имеет связанную с ним цепочку областей. Эта область цепочка-это список или цепочка объектов, которые определяют переменные, которые "находятся в области" для этого код. Когда JavaScript должен искать значение переменной x (этот процесс называется разрешение переменной), он начинается с просмотра первого объекта в цепочке. Если этот объект имеет свойство с именем x, используется значение этого свойства. Если первый объект не обладающий свойство с именем x , JavaScript продолжает поиск со следующим объектом в цепочке. Если второй объект не имеет свойства с именем x, поиск переходит к следующему возражение и так далее. Если x не является свойством любого из объектов в цепочке областей, тогда x не входит в область действия этого кода, и возникает ReferenceError. В коде JavaScript верхнего уровня (т. е. коде, не содержащемся в определениях функций), цепочка областей состоит из одного объект, глобальный объект. В не вложенной функции, цепочка областей состоит из двух объектов. Первый-это объект, который определяет функции параметры и локальные переменные, а второй-глобальный объект. Во вложенной функции, цепочка областей имеет три или более объектов. Важно понимать, как работает эта цепочка объектов создается. Когда функция определена, он сохраняет цепочку области действия. Когда эта функция вызывается, он создает новый объект для хранения локальных переменных, и добавляет, что новый объект хранимой scope-цепь для создания нового, более, цепь, представляет область для вызова этой функции. Это становится более интересным для вложенные функции, потому что каждый раз, когда внешняя функция, внутренняя функция опять-таки определенными. Поскольку цепочка областей отличается при каждом вызове внешней функции, внутренняя функция будет тонко отличаться каждый раз, когда она определена-код внутренний функция будет идентично при каждом вызове внешней функции, но цепочка областей связанный с этим кодом будет отличаться. Это понятие цепочки охвата имеет решающее значение для понимания замыканий.


попробуйте этот любопытный пример. В приведенном ниже примере, если бы a был числовым, инициализированным в 0, вы бы увидели 0, а затем 1. Кроме того, A является объектом, и javascript передаст f1 указатель a, а не его копию. В результате вы оба раза получаете одно и то же предупреждение.

var a = new Date();
function f1(b)
{
    b.setDate(b.getDate()+1);
    alert(b.getDate());
}
f1(a);
alert(a.getDate());

Я понимаю, что есть 3 области: глобальная область, доступная глобально; локальная область, доступная для всей функции независимо от блоков; и область блока, доступная только для блока, оператора или выражения, на котором она была использована. Глобальная и локальная область обозначаются ключевым словом "var", либо внутри функции, либо снаружи, а область блока-ключевым словом "let".

для тех, кто считает, что существует только глобальная и локальная область, пожалуйста, объясните, почему Mozilla будет иметь целую страницу, описывающую нюансы области блока в JS.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let


в JavaScript существует два типа области:

  • локальная область
  • глобальный масштаб

функция ниже имеет переменную локальной области carName. И эта переменная недоступна извне функции.

function myFunction() {
    var carName = "Volvo";
    alert(carName);
    // code here can use carName
}

ниже класс имеет переменную глобальной области carName. И эта переменная доступна отовсюду в классе.

class {

    var carName = " Volvo";

    // code here can use carName

    function myFunction() {
        alert(carName);
        // code here can use carName 
    }
}

в EcmaScript5, есть в основном две области, локальная область и глобальный масштаб но в EcmaScript6 у нас есть в основном три области, локальная область, глобальная область и новая область под названием блок рамки.

пример области блока: -

for ( let i = 0; i < 10; i++)
{
 statement1...
statement2...// inside this scope we can access the value of i, if we want to access the value of i outside for loop it will give undefined.
}

ECMAScript 6 ввел ключевые слова let и const. Эти ключевые слова можно использовать вместо ключевого слова var. В отличие от ключевого слова var, ключевые слова let и const поддерживают объявление локальной области внутри операторов блока.

var x = 10
let y = 10
const z = 10
{
  x = 20
  let y = 20
  const z = 20
  {
    x = 30
    // x is in the global scope because of the 'var' keyword
    let y = 30
    // y is in the local scope because of the 'let' keyword
    const z = 30
    // z is in the local scope because of the 'const' keyword
    console.log(x) // 30
    console.log(y) // 30
    console.log(z) // 30
  }
  console.log(x) // 30
  console.log(y) // 20
  console.log(z) // 20
}

console.log(x) // 30
console.log(y) // 10
console.log(z) // 10

ES5 и старше:

переменные в Javascript были изначально (pre ES6) функция, область видимости. Термин лексически ограниченный означает, что вы можете видеть область переменных, "глядя" на код.

каждая переменная, объявленная с var ключевое слово ограничено функцией. Однако, если в этой функции объявлена другая функция, эти функции будут иметь доступ к переменным внешних функций. Это называется объем цепь. Он работает следующим образом:

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

пример:

// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';

function outerFunc () {
 // outerFunc scope
 var foo = 'outerFunc';
 var foobar = 'outerFunc';
 innerFunc();
 
 function innerFunc(){
 // innerFunc scope
  var foo = 'innerFunc';
  console.log(foo);
  console.log(bar);
  console.log(foobar);
  }
}

outerFunc();

что происходит, когда мы пытаемся войти в переменных foo, bar и foobar в консоли следующее:

  1. мы пытаемся войти в foo консоль, foo можно найти внутри функции . Поэтому значение foo разрешается в строку innerFunc.
  2. мы пытаемся войти в панель консоли, панель не может быть найдена внутри функции . Поэтому нам нужно поднимитесь на цепь прицела. Сначала мы рассмотрим внешнюю функцию, в которой функция . Это функция outerFunc. В рамках outerFunc мы можем найти переменную bar, которая содержит строку 'outerFunc'.
  3. foobar не может быть найден в innerFunc. . Поэтому нам нужно поднимитесь на цепь прицела к области innerFunc. Ее также нельзя найти здесь, мы поднимаемся на другой уровень к глобальные масштабы (т. е. самая внешняя область). Здесь мы находим переменную foobar, которая содержит строку "global". Если бы он не нашел переменную после восхождения на цепочку прицела, двигатель JS бросил бы referenceError.

ES6 (ES 2015) и старше:

те же понятия лексически область и scopechain в ES6. Однако были введены новые способы объявления переменных. Есть следующие:

  • let: создает блок переменной
  • const: создает переменную области блока, которая должна быть инициализирована и не может быть переназначена

самая большая разница между var и let/const это var является функцией области, тогда как let/const это блок. Вот пример, иллюстрирующий это:

let letVar = 'global';
var varVar = 'global';

function foo () {
  
  if (true) {
    // this variable declared with let is scoped to the if block, block scoped
    let letVar = 5;
    // this variable declared with let is scoped to the function block, function scoped
    var varVar = 10;
  }
  
  console.log(letVar);
  console.log(varVar);
}


foo();

в приведенном выше примере letVar регистрирует значение global, потому что переменные объявлены с let это блок. Они перестают существовать вне своего соответствующего блока, поэтому переменная не может быть доступна вне блока if.


в JavaScript есть два типа областей.

  1. глобальный масштаб: переменная, которая объявлена в глобальной области, может использоваться в любом месте программы очень плавно. Например:

    var carName = " BMW";
    
    // code here can use carName
    
    function myFunction() {
         // code here can use carName 
    }
    
  2. функциональная область или локальная область: переменная, объявленная в этой области, может использоваться только в своей собственной функции. Например:

    // code here can not use carName
    function myFunction() {
       var carName = "BMW";
       // code here can use carName
    }
    

глобальная переменная, объявленная вне функции

Local: переменная, объявленная внутри функции, и может быть вызвана только в этой области