Функция обзора и подъема Javascript

Я просто прочитал замечательную статью о JavaScript Scoping and Hoisting от Ben Cherry, в которой он приводит следующий пример:

var a = 1;

function b() {
    a = 10;
    return;

    function a() {}
}
b();
alert(a);

Используя приведенный выше код, браузер будет предупреждать "1".

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

Ответ 1

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

function b() {  
   a = 10;  
   return;  
   function a() {} 
} 

будет переписан интерпретатором на этот

function b() {
  function a() {}
  a = 10;
  return;
}

Странно, а??

Кроме того, в этом случае

function a() {}

вел себя так же, как

var a = function () {};

Итак, по сути, это то, что делает код:

var a = 1;                 //defines "a" in global scope
function b() {  
   var a = function () {}; //defines "a" in local scope 
   a = 10;                 //overwrites local variable "a"
   return;      
}       
b();       
alert(a);                 //alerts global variable "a"

Ответ 2

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

function a() {} 

действительно становится

var a = function () {}

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

Ответ 3

Функция a находится внутри функции b:

var a = 1; 
function b() { 
   function a() {} 
   a = 10; 
   return;
} 
b(); 
alert(a);

что почти похоже на использование var:

var a = 1; 
function b() { 
   var a = function () {};
   a = 10; 
   return;
} 
b(); 
alert(a);

Функция объявляется локально, а установка a происходит только в локальной области, а не в глобальном var.

Ответ 4

  • Объявление функции function a(){} выполняется сначала, и оно ведет себя как var a = function () {};, поэтому в локальной области a создается.
  • Если у вас есть две переменные с одинаковым именем (одно в глобальном другом в локальном), локальная переменная всегда получает приоритет над глобальной переменной.
  • Когда вы устанавливаете a=10, вы устанавливаете локальную переменную a, а не глобальную.

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

Ответ 5

function a() { } - это оператор функции, который создает переменную a, локальную для функции b.
Переменные создаются при анализе функции независимо от того, выполняется ли оператор var или function.

a = 10 устанавливает эту локальную переменную.

Ответ 6

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

Когда появляются объявления, var a, затем function b и внутри этой области b объявляется function a.

Эта функция a затеняет переменную a, исходящую из глобальной области.

После того, как объявления будут выполнены, начнется назначение значений, глобальное a получит значение 1, а a внутри function b получит 10. когда вы сделаете alert(a), он вызовет фактическую глобальную переменную области видимости. Это небольшое изменение кода сделает его более понятным.

        var a = 1;

    function b() {
        a = 10;
        return a;

        function a() { }
    }

    alert(b());
    alert(a);

Ответ 7

scpope и закрытие и подъем (var/function)

  • scpope: глобальный var может быть доступен в любом месте (весь файл область), локальный var может быть доступен только локальным scope (область функций/блоков)!
    Примечание: если локальная переменная не используется var ключевые слова в функции, он станет глобальной переменной!Закрытие
  • : внутренняя функция - другая функция, доступ к которой локальная область действия (родительская функция) и глобальная область действия, howerver it vars не могут быть доступны другим! если вы не вернете его в качестве возвращаемого значения!
  • hoisting: переместить все объявить/ундекларировать vars/function в область сверху, чем назначить значение или null!
    Примечание: он просто перемещает объявление, а не перемещает значение!

var a = 1;                
//"a" is global scope
function b() {  
   var a = function () {}; 
   //"a" is local scope 
   var x = 12; 
   //"x" is local scope 
   a = 10;
   //global variable "a" was overwrited by the local variable "a"  
   console.log("local a =" + a);
   return console.log("local x = " + x);
}       
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x = 
console.log(x);
// ReferenceError: x is not defined

Ответ 8

В чем состоит суть этого небольшого фрагмента кода?

Случай 1:

Включить определение function a(){} внутри тела function b следующим образом. logs value of a = 1

var a = 1;
function b() {
  a = 10;
  return;

  function a() {}
}
b();
console.log(a); // logs a = 1

Случай 2

Исключить function a(){} определение внутри тела function b следующим образом. logs value of a = 10

var a = 1;
function b() {
  a = 10;  // overwrites the value of global 'var a'
  return;
}
b();
console.log(a); // logs a = 10

Наблюдение поможет вам понять, что оператор console.log(a) регистрирует следующие значения.

Случай 1: a = 1

Случай 2: a = 10

постулирует

  • var a был определен и объявлен лексически в глобальной области.
  • a=10 Этот оператор переназначает значение 10, он лексически находится внутри функции b.

Объяснение обоих случаев

Из-за function definition with name property a аналогичен variable a. variable a внутри function body b становится локальной переменной. В предыдущей строке подразумевается, что глобальное значение a остается неповрежденным, а локальное значение a обновляется до 10.

Итак, мы намерены сказать, что код ниже

var a = 1;
function b() {
  a = 10;
  return;

  function a() {}
}
b();
console.log(a); // logs a = 1

Он интерпретируется интерпретатором JS следующим образом.

var a = 1;
function b() {
  function a() {}
  a = 10;
  return;


}
b();
console.log(a); // logs a = 1

Однако, когда мы удаляем function a(){} definition, value of 'a', объявленный и определенный вне функции b, это значение перезаписывается, и оно изменяется на 10 в случае 2. Значение перезаписывается, поскольку a=10 относится к глобальному декларации, и если он должен быть объявлен локально, мы должны написать var a = 10;.

var a = 1;
function b() {
  var a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;
}
b();
console.log(a); // logs a = 1

Мы можем уточнить наши сомнения, изменив name property в function a(){} definition на другое имя, чем 'a'

var a = 1;
function b() {
  a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;

  function foo() {}
}
b();
console.log(a); // logs a = 1

Ответ 9

Это происходит из-за того, что имя переменной совпадает с именем функции "a". Таким образом, из-за Javascript hoisting он пытается решить конфликт имен и он вернет a = 1.

Я тоже был смущен, пока я не прочитал этот пост в разделе "Подъем JavaScript" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Надеюсь, что это поможет.

Ответ 10

Здесь мой ответ ответа с большей аннотацией и акустической игрой, с которой можно поиграть.

// hoisting_example.js

// top of scope ie. global var a = 1
var a = 1;

// new scope due to js' functional (not block) level scope
function b() {
    a = 10; // if the function 'a' didn't exist in this scope, global a = 10
  return; // the return illustrates that function 'a' is hoisted to top
  function a(){}; // 'a' will be hoisted to top as var a = function(){};
}

// exec 'b' and you would expect to see a = 10 in subsequent alert
// but the interpreter acutally 'hoisted' the function 'a' within 'b' 
// and in doing so, created a new named variable 'a' 
// which is a function within b scope
b();

// a will alert 1, see comment above
alert(a);

https://jsfiddle.net/adjavaherian/fffpxjx7/

Ответ 11

Длинная почта!

Но это очистит воздух!

Способ работы Java Script состоит в том, что он включает в себя двухэтапный процесс:

  • Компиляция (так сказать). Этот шаг регистрирует объявления переменных и функций и их соответствующую область. Это не связано с оценкой выражения функции: var a = function() {} или выражение переменной (например, присвоение 3 x в случае var x = 3;, который является не чем иным, как оценкой части RHS.)

  • Интерпретатор: это часть выполнения/оценки.

Проверьте вывод ниже кода, чтобы понять:

 //b() можно вызвать здесь!
//c () не может быть вызван.
console.log( "a is"  + a);
console.log( "b -" + b);
console.log( "c is" + c);
var a = 1;
console.log( "Теперь, a есть" + a);
var c = function() {};
console.log( "Теперь c есть" + c);

функция b() {
 // не могу написать следующую строку:
 //console.log(e);
 // поскольку e не объявлен.
 e = 10;//интерпретатор Java-скрипта после прохождения от этой цепочки видимости этой функции до глобальной области, не может найти эту переменную и в конечном итоге инициализирует ее значением 10 в глобальной области.
 console.log( "e is" + e) ​​//работает!
 console.log( "f есть" + f);
 var f = 7;
 console.log( "Теперь f есть" + f);
 console.log( "d is" + d);
 вернуть;

 функция d() {}
}
б();
console.log(а);код>

Ответ 12

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

Ответ 13

Все зависит от области действия переменной "a". Позвольте мне объяснить, создав области как изображения.

Здесь JavaScript создаст 3 области.

i) Глобальный охват. ii) Область действия b(). iii) Функция a() scope.

введите описание изображения здесь

Ясность, когда вы вызываете область действия "alert", принадлежит глобальному времени, поэтому она будет выбирать значение переменной "a" из глобальной области видимости только 1.

Ответ 14

Подъем - поведенческая концепция JavaScript. Подъем (скажем, перемещение) - это концепция, которая объясняет, как и где должны быть объявлены переменные.

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

В большинстве случаев мы сталкиваемся с двумя типами подъема.

1. Переменная декларация объявления

Давайте рассмотрим этот фрагмент кода.

 a = 5; // Assign 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
 var a; // Declare a
  //output-> 5

Здесь объявление переменной a будет отображаться невидимым с помощью интерпретатора javascript во время компиляции. Таким образом, мы смогли получить значение a. Но этот подход декларации переменных не рекомендуется, так как мы должны объявлять переменные сверху так же, как это.

 var a = 5; // Assign and declare 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
  // output -> 5

рассмотрим другой пример.

  function foo() {
     console.log(x)
     var x = 1;
 }

фактически интерпретируется так:

  function foo() {
     var x;
     console.log(x)
     x = 1;
  }

В этом случае x будет неопределенным

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

  function foo() {
     if (false) {
         var a = 1;
     }
     return;
     var b = 1;
  }

Эта функция оказывается такой.

  function foo() {
      var a, b;
      if (false) {
        a = 1;
     }
     return;
     b = 1;
  }

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

  1. Подтверждение объявления функции

В отличие от подъема переменной, будет также поднят корпус функции или назначенное значение. Рассмотрим этот код

 function demo() {
     foo(); // this will give error because it is variable hoisting
     bar(); // "this will run!" as it is function hoisting
     var foo = function () {
         alert("this would not run!!");
     }
     function bar() { 
         alert("this will run!!");
     }
 }
 demo();

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

var a = 1;
function b() {
  a = 10;
  return;
   function a() {}
}
b();
alert(a);

Этот код окажется таким.

var a = 1;                 //defines "a" in global scope
 function b() {  
   var a = function () {}; //defines "a" in local scope 
    a = 10;                 //overwrites local variable "a"
    return;      
 }       
 b();       
 alert(a); 

Функция a() будет иметь локальную область внутри b(). a() будет перемещен в начало при интерпретации кода с его определением (только в случае подъема функции), так что теперь у него будет локальная область действия и, следовательно, не повлияет на глобальную область while, имеющую собственную область внутри функции b(),

Ответ 15

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

Механизм JavaScript помещает исполняемый в данный момент код в контекст выполнения. Базовый контекст выполнения - это глобальный контекст выполнения. Каждый раз, когда вызывается новая функция, создается новый контекст выполнения и помещается в стек выполнения. Подумайте о стеке стека, расположенном в стеке вызовов на других языках программирования. Последний в первом вышел. Теперь каждый контекст выполнения имеет свою собственную переменную среду и внешнюю среду в JavaScript.

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

1) Сначала мы входим в фазу создания глобального контекста выполнения. И внешняя среда, и переменная среда лексической среды созданы. Глобальный объект настраивается и помещается в память со специальной переменной "this", указывающей на него. Функция a и ее код, а также переменная myVar с неопределенным значением помещаются в память в глобальной переменной среде. Важно отметить, что функция кода не выполняется. Он просто помещается в память с функцией a.

2) Во-вторых, это фаза выполнения контекста выполнения. myVar больше не является неопределенным значением. Он инициализируется значением 1, которое хранится в глобальной переменной среде. Вызывается функция a и создается новый контекст выполнения.

3) В функции "Контекст выполнения" она проходит фазу создания и выполнения своего собственного контекста выполнения. Он имеет свою собственную внешнюю среду и переменную среду, то есть свою собственную лексическую среду. Функция b и переменная myVar хранятся в своей переменной среды. Эта переменная среда отличается от глобальной переменной среды. Поскольку функция a лексически (физически в коде) находится на том же уровне, что и глобальный контекст выполнения, ее внешняя среда является глобальным контекстом выполнения. Таким образом, если функция a должна ссылаться на переменную, отсутствующую в ее среде переменных, она выполнит поиск в цепочке областей действия и попытается найти переменную в среде переменных глобального контекста выполнения.

4) Функция b вызывается в функции a. Новый контекст выполнения создан. Поскольку он находится в функции a лексически, его Внешняя среда - это. Поэтому, когда он ссылается на myVar, поскольку myVar не находится в функции b Variable Environment, он будет выглядеть в функции Variable Environment. Он находит его там, и console.log печатает 2. Но если переменная не была в функции Variable Environment, то, поскольку функция Outer Environment является глобальным контекстом выполнения, цепочка областей действия продолжит поиск там.

5) После завершения выполнения функций b и a они извлекаются из стека выполнения. Однопоточный движок JavaScript продолжает выполнение в глобальном контексте выполнения. Он вызывает функцию b. Но в глобальной среде переменных нет функции b, и нет другой внешней среды для поиска в глобальном контексте выполнения. Таким образом, механизм JavaScript создает исключение.

function a(){
  function b(){
    console.log(myVar);
  }

  var myVar = 2;
  b();
}

var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined

В приведенном ниже примере показана цепочка областей действия в действии. В функции b Среда переменных контекста выполнения отсутствует myVar. Таким образом, он ищет свою внешнюю среду, которая является функцией а. Функция a также не имеет myVar в своей переменной. Таким образом, Механизм поиска выполняет функцию Внешняя среда, которая является глобальной Внешней средой контекста выполнения, и в ней определяется myVar. Следовательно, console.log печатает 1.

function a(){
  function b(){
    console.log(myVar);
  }

  b();
}

var myVar = 1;
a();
> 1

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

Ответ 16

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

a = 7;
var a;
console.log(a) 

Что происходит внутри движка JavaScript:

var a;
a = 7;
console.log(a);
// 7

Или:

console.log(square(7)); // Output: 49
function square(n) { return n * n; }

Это станет:

function square(n) { return n * n; }
console.log(square(7)); // 49

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

console.log(x);
var x = 7; // undefined

Это может стать так:

var x;
console.log(x); // undefined
x = 7;