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

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

Итак, если вы используете Angular, React или любые другие фреймворки, которые делают два способа связывания данных, эта проблема просто исправлена ​​для вас, поэтому простым языком ваш результат undefined на первом этапе, поэтому вы получили result = undefined до получения данных, а затем, как только вы получите результат , он будет обновляться и присваиваться новому значению, которое отвечает на ваш вызов Ajax ...

Но как вы можете сделать это в чистом javascript или jQuery, например, как вы задали этот вопрос?

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

Например, в вашем случае, в котором вы используете jQuery, вы можете сделать что-то вроде этого:

$(document).ready(function(){
    function foo() {
        $.ajax({url: "api/data", success: function(data){
            fooDone(data); //after we have data, we pass it to fooDone
        }});
    };

    function fooDone(data) {
        console.log(data); //fooDone has the data and console.log it
    };

    foo(); //call happens here
});

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

72
задан thefourtheye 17 April 2015 в 13:44
поделиться

13 ответов

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

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

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

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

Weird, eh?

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

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"
103
ответ дан Peter Olson 24 August 2018 в 21:27
поделиться

Вот мое резюме ответа с большей аннотацией и акустической скрипкой, чтобы поиграть с ней.

// 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's scope
b();

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

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

0
ответ дан 4m1r 24 August 2018 в 21:27
поделиться

Long Post!

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

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

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

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

//b() can be called here!
//c() cannot be called.
console.log("a is " + a);
console.log("b is " + b);
console.log("c is " + c);
var a = 1;
console.log("Now, a is " + a);
var c = function() {};
console.log("Now c is " + c);

function b() {
  //cannot write the below line:
  //console.log(e); 
  //since e is not declared.
  e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
  console.log("e is " + e) //  works!
  console.log("f is " + f);
  var f = 7;
  console.log("Now f is " + f);
  console.log("d is " + d);
  return;

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

Позволяет разбить его:

  1. На этапе компиляции «a» будет зарегистрирован в глобальной области действия со значением «undefined». То же самое касается «c», его значение в этот момент будет «undefined», а не «function()». 'b' будет зарегистрирован как функция в глобальном масштабе. Внутри области b '' f 'будет зарегистрирована как переменная, которая в данный момент не определена, и функция [d' будет зарегистрирована.
  2. Когда интерпретатор запускается, объявленные переменные и function() (а не выражения) могут быть доступны до того, как интерпретатор достигнет фактической строки выражения. Таким образом, переменные будут напечатаны «undefined», а анонимная функция может быть вызвана ранее. Однако, пытаясь получить доступ к необъявленной переменной до того, как ее инициализация выражения приведет к ошибке, например:

console.log(e)
e = 3;

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

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

var a = 1;
console.log("a is " + a);

function b() {
  console.log("a inside the function b is " + a); //interpreter finds                                'a' as function() in current scope. No need to go outside the scope to find 'a'.
  a = 3; //a changed
  console.log("Now a is " + a);
  return;

  function a() {}
}
var a; //treated as duplicate and ignored.
b();
console.log("a is still " + a + " in global scope"); //This is global scope a.

1
ответ дан antzshrek 24 August 2018 в 21:27
поделиться

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

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

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

0
ответ дан AugustRush 24 August 2018 в 21:27
поделиться

Функция 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.

5
ответ дан Digital Plane 24 August 2018 в 21:27
поделиться

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

function a() {} 

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

var a = function () {}

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

6
ответ дан kemiller2002 24 August 2018 в 21:27
поделиться
  1. Объявление функции function a(){} сначала вставлено, и оно ведет себя как var a = function () {};, поэтому в локальной области a создается.
  2. Если у вас есть две переменные с одинаковым именем (одно в глобальном другом в локальном), локальная переменная всегда получает приоритет над глобальной переменной.
  3. Когда вы устанавливаете a=10, вы устанавливаете локальную переменную a, а не глобальную.

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

3
ответ дан KhanSharp 24 August 2018 в 21:27
поделиться

Подъем - поведенческая концепция 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 () .

0
ответ дан melpomene 24 August 2018 в 21:27
поделиться

Какова суть разногласий в этом небольшом фрагменте кода?

Случай 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

Положительные

  1. var a определены и объявлен лексически в глобальном масштабе.
  2. 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
0
ответ дан Sagar Munjal 24 August 2018 в 21:27
поделиться

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

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

1
ответ дан SLaks 24 August 2018 в 21:27
поделиться

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

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

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

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

0
ответ дан Sumit Pahuja 24 August 2018 в 21:27
поделиться

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

0
ответ дан Vishwas S L 24 August 2018 в 21:27
поделиться

scpope & amp; закрытие & amp; hiisting (var / function)

  1. scpope: глобальный var может быть доступен в любом месте (весь объем файла), локальный var может быть доступен только локальной областью (функция / область блока)! Примечание: если локальная переменная не использует переменные var в функции, она станет глобальной переменной!
  2. close: функция внутренняя, другая функция, которая может обращаться к локальной области (родительская функция) & amp; глобальный охват, howerver, к которым его нельзя открыть другим! если вы не вернете его в качестве возвращаемого значения!
  3. 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

1
ответ дан xgqfrms 24 August 2018 в 21:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: