Je viens de lire un excellent article sur JavaScript Scoping and Hoisting par Ben Cherry dans lequel il donne l'exemple suivant:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
En utilisant le code ci-dessus, le navigateur alertera "1".
Je ne sais toujours pas pourquoi il renvoie "1". Certaines des choses qu'il dit viennent à l'esprit comme: Toutes les déclarations de fonction sont hissées vers le haut. Vous pouvez définir une variable à l'aide de function. Ne clique toujours pas pour moi.
javascript
scope
scoping
hoisting
développeur
la source
la source
var a
doit être avant la déclaration de fonction et l'affectationa = 1
doit être après. Mais notez que cela n'est pas spécifié pour se produire réellement par l'analyseur, le tokeniseur, l'interpréteur, le compilateur, peu importe, c'est juste un équivalent.function a() {}
s'est comporté de la même manière quevar a = function () {};
" - ceci est incorrect de deux manières: d'abord, si quelque chose aurait étévar a = function a() {};
(la fonction n'est en fait pas anonyme), deuxièmement, ces deux formes ne sont pas interchangeables, car à partir devar a = function a() {};
seule lavar a;
partie aurait été hissée. Laa = function a() {};
pièce aurait toujours été derrière la déclaration de retour. Étant donné que le formulaire d'origine est une déclaration de fonction et non une expression de fonction, il est en fait hissé dans son ensemble.Ce que vous devez vous rappeler, c'est qu'il analyse l'ensemble de la fonction et résout toutes les déclarations de variables avant de l'exécuter. Alors....
devient vraiment
var a
la force dans une portée locale, et la portée de la variable s'étend sur toute la fonction, donc la variable globale a est toujours 1 parce que vous avez déclaré a dans une portée locale en en faisant une fonction.la source
La fonction
a
est hissée à l'intérieur de la fonctionb
:ce qui revient presque à utiliser
var
:La fonction est déclarée localement et la configuration
a
ne se produit que dans la portée locale, pas dans la variable globale.la source
function a(){}
est levée en premier et elle se comporte commevar a = function () {};
, par conséquent, la portée localea
est créée.a=10
, vous définissez la variable localea
, pas la variable globale.Par conséquent, la valeur de la variable globale reste la même et vous obtenez, alerté 1
la source
function a() { }
est une instruction de fonction, qui crée unea
variable locale à lab
fonction.Les variables sont créées lorsqu'une fonction est analysée, que le
var
instruction de fonction ou soit exécutée.a = 10
définit cette variable locale.la source
a = 10
définit en fait une variable dans la portée globale lorsque la fonctionb
est exécutée sauf si vous ajoutez"use strict"
(dans des environnements tels que la prise en charge de cette directive).Quelle est la pomme de discorde dans ce petit bout de code?
Cas 1:
Incluez la
function a(){}
définition dans le corps defunction b
comme suit.logs value of a = 1
Cas 2
Excluez la
function a(){}
définition à l'intérieur du corps defunction b
comme suit.logs value of a = 10
L'observation vous aidera à réaliser cette déclaration
console.log(a)
enregistre les valeurs suivantes.Cas 1 : a = 1
Cas 2: a = 10
Posits
var a
a été défini et déclaré lexicalement dans la portée globale.a=10
Cette instruction réaffecte la valeur à 10, elle se trouve lexicalement à l'intérieur de la fonction b.Explication des deux cas
En raison d'
function definition with name property
un est le même que levariable a
. L'variable a
intérieurfunction body b
devient une variable locale. La ligne précédente implique que la valeur globale de a reste intacte et que la valeur locale de a est mise à jour à 10.Donc, ce que nous avons l'intention de dire, c'est que le code ci-dessous
Il est interprété par l'interpréteur JS comme suit.
Cependant, lorsque nous supprimons le
function a(){} definition
, levalue of 'a'
déclaré et défini en dehors de la fonction b, cette valeur est écrasée et passe à 10 dans le cas 2. La valeur est écrasée cara=10
fait référence à la déclaration globale et si elle devait être déclarée localement, nous devons avoir écritvar a = 10;
.Nous pouvons clarifier davantage notre doute en changeant le
name property
infunction a(){} definition
en un autre nom que'a'
la source
Le levage est un concept fait pour nous pour le rendre plus facile à comprendre. Ce qui se passe en fait, c'est que les déclarations sont faites en premier par rapport à leurs portées et les affectations se produiront ensuite (pas en même temps).
Lorsque les déclarations se produisent,
var a
alorsfunction b
et à l'intérieur de cetteb
portée,function a
est déclaré.Cette fonction a occultera la variable a provenant de la portée globale.
Une fois les déclarations faites, les valeurs assignées commenceront, le global
a
obtiendra la valeur1
et le a insidefunction b
obtiendra10
. lorsque vous le faitesalert(a)
, il appellera la variable de portée globale réelle. Ce petit changement au code le rendra plus clairla source
Étonnamment, aucune des réponses ici ne mentionne la pertinence du contexte d'exécution dans la chaîne de portée.
Le moteur JavaScript encapsule le code en cours d'exécution dans un contexte d'exécution. Le contexte d'exécution de base est le contexte d'exécution global. Chaque fois qu'une nouvelle fonction est appelée, un nouveau contexte d'exécution est créé et placé sur la pile d'exécution. Pensez à un cadre de pile assis sur une pile d'invocation dans d'autres langages de programmation. Dernier entré, premier sorti. Désormais, chaque contexte d'exécution a son propre environnement variable et son propre environnement externe en JavaScript.
J'utiliserai l'exemple ci-dessous comme démonstration.
1) Tout d'abord, nous entrons dans la phase de création du contexte global d'exécution. L'environnement extérieur et l'environnement variable de l'environnement lexical sont créés. L'objet global est configuré et placé en mémoire avec la variable spéciale «this» pointant vers lui. La fonction a et son code et la variable myVar avec une valeur indéfinie sont placés en mémoire dans l'environnement variable global. il est important de noter que le code de la fonction a n'est pas exécuté. Il est simplement mis en mémoire avec la fonction a.
2) Deuxièmement, c'est la phase d'exécution du contexte d'exécution. myVar n'est plus une valeur indéfinie. Il est initialisé avec la valeur 1, qui est stockée dans l'environnement variable global. La fonction a est appelée et un nouveau contexte d'exécution est créé.
3) Dans le contexte d'exécution de la fonction a, elle passe par la phase de création et d'exécution de son propre contexte d'exécution. Il a son propre environnement extérieur et son environnement variable, donc son propre environnement lexical. La fonction b et la variable myVar sont stockées dans son environnement variable. Cet environnement variable est distinct de l'environnement variable global. Puisque la fonction a se situe lexicalement (physiquement dans le code) au même niveau que le contexte d'exécution global, son environnement extérieur est le contexte d'exécution global. Ainsi, si la fonction a faisait référence à une variable qui n'est pas dans son environnement variable, elle recherchera la chaîne de portée et tentera de trouver la variable dans l'environnement variable du contexte d'exécution global.
4) La fonction b est appelée dans la fonction a. Un nouveau contexte d'exécution est créé. Puisqu'il se trouve lexicalement dans la fonction a, son environnement extérieur est a. Ainsi, quand il fait référence à myVar, puisque myVar n'est pas dans l'environnement variable de la fonction b, il cherchera dans l'environnement variable de la fonction a. Il le trouve là et console.log imprime 2. Mais si la variable n'était pas dans l'environnement variable de la fonction a, alors puisque l'environnement extérieur de la fonction a est le contexte d'exécution global, alors la chaîne de portées continuera à y chercher.
5) Une fois l'exécution des fonctions b et a terminée, elles sont extraites de la pile d'exécution. Le moteur JavaScript monothread continue son exécution dans le contexte d'exécution global. Il invoque la fonction b. Mais il n'y a pas de fonction b dans l'environnement variable global et il n'y a pas d'autre environnement externe à rechercher dans le contexte d'exécution global. Ainsi, une exception est déclenchée par le moteur JavaScript.
L'exemple ci-dessous montre la chaîne de portée en action. Dans l'environnement variable du contexte d'exécution de la fonction b, il n'y a pas de myVar. Il recherche donc son environnement extérieur, qui est la fonction a. La fonction a n'a pas non plus myVar dans son environnement variable. Ainsi, les recherches du moteur fonctionnent dans l'environnement externe de a, qui est l'environnement externe du contexte d'exécution global et myVar y est défini. Par conséquent, console.log imprime 1.
En ce qui concerne le contexte d'exécution et l'environnement lexical qui lui est associé, y compris l'environnement externe et l'environnement variable, activez la portée des variables dans JavaScript. Même si vous appelez la même fonction plusieurs fois, pour chaque appel, elle créera son propre contexte d'exécution. Ainsi, chaque contexte d'exécution aura sa propre copie des variables dans son environnement variable. Il n'y a pas de partage de variables.
la source
Cela se produit parce que le nom de la variable est le même que le nom de la fonction signifie "a". Ainsi, en raison du levage de Javascript, il essaie de résoudre le conflit de nom et il retournera a = 1.
J'étais également confus à ce sujet jusqu'à ce que je lis ce post sur "JavaScript Hoisting" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html
J'espère que ça aide.
la source
Voici mon récapitulatif de la réponse avec plus d'annotations et un violon d'accompagnement avec lequel jouer.
https://jsfiddle.net/adjavaherian/fffpxjx7/
la source
portée et fermeture et levage (var / fonction)
la source
Levage En JavaScript signifie, les déclarations de variables sont exécutées tout au long du programme avant l'exécution de tout code. Par conséquent, déclarer une variable n'importe où dans le code équivaut à la déclarer au début.
la source
Tout dépend de la portée de la variable «a». Laissez-moi vous expliquer en créant des portées sous forme d'images.
Ici, JavaScript créera 3 portées.
i) Portée mondiale. ii) Portée de la fonction b (). iii) Fonction a () portée.
Son clair lorsque vous appelez la portée de la méthode 'alert' appartient à Global à ce moment-là, donc il choisira la valeur de la variable 'a' dans la portée Global uniquement qui est 1.
la source
Long Post!
Mais ça va purifier l'air!
Le fonctionnement de Java Script est qu'il implique un processus en deux étapes:
Compilation (pour ainsi dire) - Cette étape enregistre les variables et les déclarations de fonction et leur portée respective. Cela n'implique pas l'évaluation de l'expression de fonction:
var a = function(){}
ou de l'expression de variable (comme l'attribution3
dex
in casevar x =3;
qui n'est rien d'autre que l'évaluation de la partie RHS.)Interprète: Il s'agit de la partie exécution / évaluation.
Vérifiez la sortie du code ci-dessous pour comprendre:
Permet de le casser:
Dans la phase de compilation, «a» serait enregistré sous la portée globale avec la valeur «
undefined
». Il en va de même pour «c
», sa valeur à ce moment serait «undefined
» et non le «function()
». 'b
' serait enregistré en tant que fonction dans la portée globale. Dansb
la portée de 'f
' , ' ' serait enregistré comme une variable qui ne serait pas définie à ce moment et la fonction 'd
' serait enregistrée.Lorsque l'interpréteur s'exécute, les variables déclarées et
function()
(et non les expressions) sont accessibles avant que l'interpréteur n'atteigne la ligne d'expression réelle. Ainsi, les variables seraient imprimées 'undefined
' et la fonction anonyme déclarée peut être appelée plus tôt. Cependant, essayer d'accéder à une variable non déclarée avant l'initialisation de son expression entraînerait une erreur comme:Maintenant, que se passe-t-il lorsque vous avez une déclaration de variable et de fonction avec le même nom.
La réponse est - les fonctions sont toujours levées avant et si la même variable de nom est déclarée, elle est traitée comme dupliquée et ignorée. N'oubliez pas que l'ordre n'a pas d'importance. Les fonctions sont toujours prioritaires. Mais pendant la phase d'évaluation, vous pouvez modifier la référence de la variable à n'importe quoi (elle stocke ce qui était la dernière affectation) Jetez un œil au code ci-dessous:
la source
Le levage est un concept comportemental de JavaScript. Le levage (disons le déplacement) est un concept qui explique comment et où les variables doivent être déclarées.
En JavaScript, une variable peut être déclarée après avoir été utilisée car les déclarations de fonction et les déclarations de variable sont toujours déplacées («hissées») de manière invisible vers le haut de leur portée contenant par l'interpréteur JavaScript.
Nous rencontrons deux types de levage dans la plupart des cas.
1. levage de déclaration variable
Permet de comprendre cela par ce morceau de code.
Ici, la déclaration de la variable a sera hébergée en haut de manière invisible par l'interpréteur javascript au moment de la compilation. Nous avons donc pu obtenir la valeur d'un. Mais cette approche de déclaration de variables n'est pas recommandée car nous devrions déjà déclarer les variables en haut comme ceci.
prenons un autre exemple.
est en fait interprété comme ceci:
Dans ce cas, x sera indéfini
Peu importe si le code a été exécuté qui contient la déclaration de variable. Prenons cet exemple.
Cette fonction se révèle être comme ça.
Dans la déclaration de variable, seuls les ascenseurs à définition de variable, pas l'affectation.
Contrairement à la variable de levage, le corps de fonction ou la valeur assignée sera également soulevé. Considérez ce code
Maintenant que nous avons compris le levage de variables et de fonctions, comprenons maintenant ce code.
Ce code se révélera être comme ça.
La fonction a () aura une portée locale dans b (). a () sera déplacé vers le haut lors de l'interprétation du code avec sa définition (uniquement en cas de levage de fonction) donc a now aura une portée locale et n'affectera donc pas la portée globale de a tout en ayant sa propre portée dans la fonction b () .
la source
D'après mes connaissances, le levage se produit avec la déclaration de variable et la déclaration de fonction, par exemple:
Que se passe-t-il dans le moteur de JavaScript:
Ou:
Cela deviendra:
Mais les affectations telles que l'affectation de variable, l'affectation d'expression de fonction ne seront pas levées: Par exemple:
Cela peut devenir comme ça:
la source
Pour décrire l'hébergement en javascript en une phrase, les variables et les fonctions sont hissées au sommet de la portée dans laquelle elles sont déclarées.
Je suppose que vous êtes un débutant, pour bien comprendre le levage au début, nous avons compris la différence entre undefined et ReferenceError
maintenant dans le code ci-dessous ce que nous voyons? une variable et une expression de fonction sont décleard.
mais l'image réelle avec la preuve que la variable et la fonction sont hissées au-dessus de la portée:
La sortie des deux premiers journaux n'est pas définie et TypeError: getSum n'est pas une fonction car var totalAmo et getSum sont hissés au sommet de leur portée comme ci-dessous
Mais pour les fonctions de déclaration, des fonctions entières hissées au sommet de leur portée.
Maintenant, la même logique s'applique aux varibales, aux expériences de fonctions et aux déclarations de fonctions déclarées dans la portée fonctionnelle. Point clé: ils ne seront pas hissés en haut du dossier ;
Ainsi, lorsque vous utilisez le mot clé var , la variable et la fonction hissées en haut de la portée (portée globale et portée de la fonction). Qu'en est-il de let et const , const et let sont toujours conscients de la portée globale et de la portée de la fonction, tout comme var l'est, mais les variables const et let sont également conscientes d'une autre portée appelée portée bloquée. une portée de bloc est présente chaque fois qu'il y a un bloc de code, comme une boucle for, une instruction if else, une boucle while, etc.
Lorsque nous utilisons const et laissons déclarer une variable dans la portée de ces blocs, seule la déclaration de variable sera hissée en haut du bloc dans lequel elle se trouve, et elle ne sera pas hissée en haut de la fonction parent ou en haut de la portée mondiale qu’elle est hissée.
Les variables de l'exemple abobe seront hissées comme ci-dessous
la source
ES5: fonction de levage et levage variable
qui est égal à
la raison derrière le levage
ES6
let
,const
pas d'existence de levageréfs
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
la source