Maison >interface Web >js tutoriel >Introduction détaillée à la portée en JavaScript (exemple de code)

Introduction détaillée à la portée en JavaScript (exemple de code)

不言
不言avant
2019-03-11 16:59:121722parcourir

Le contenu de cet article est une introduction détaillée (exemple de code) sur la portée en JavaScript. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. aidé.

Presque tous les langages de programmation ont le concept de portée, alors à quoi fait référence exactement la portée ? La portée est un ensemble de règles sur la façon dont les variables sont stockées et accessibles lorsqu'un langage de programmation définit des variables. Les règles des différents langages de programmation sont similaires. Voyons ensuite comment cet ensemble de règles est défini

Principe de compilation

Dans les langages compilés traditionnels, il existe un processus de compilation avant l'exécution du code :

    Segmentation de mots/analyse lexicale : décomposer les instructions de code en code significatif blocs, également appelés unités lexicales.
  • Parsing/analyse grammaticale : convertir les unités lexicales en une structure arborescente avec des règles grammaticales imbriquées niveau par niveau, également appelée arbre de syntaxe abstraite (AST)
  • Génération de code : analyser l'AST et convertir les instructions machine
sont différents des langages compilés traditionnels. La compilation et l'exécution de js ne sont pas exécutées séparément. Dans la plupart des cas, le processus de compilation sera exécuté immédiatement après la fin. performances optimales dans le délai imparti, le moteur js est plus complexe que le compilateur général. Jetons maintenant un œil au processus de compilation js. Prenons simplement la compilation de var a = 2 comme exemple :

Lorsqu'il rencontre var a, le compilateur demandera à la portée si une variable portant ce nom existe déjà dans la collection de la même portée. Si tel est le cas, le compilateur ignorera la déclaration et poursuivra la compilation ; sinon, il demandera à la portée de déclarer une nouvelle variable a
  • dans la collection de la portée actuelle. Ensuite, le compilateur générera des informations d'exécution pour le moteur. Le code requis est utilisé pour gérer l'opération d'affectation a=2. Lorsque le moteur tourne, il demandera d'abord à la portée s'il existe une variable appelée a dans l'ensemble de portées actuel. Sinon, le moteur utilisera cette variable ; si le moteur trouve finalement un, il lui attribuera 2. Sinon, le moteur lancera une exception
Portée lexicale

Portée a généralement deux modèles de travail, le premier est utilisé par la plupart des langages de programmation L'autre type de La portée lexicale utilisée est appelée portée dynamique. Par exemple, le script Bash utilise la portée dynamique. La portée lexicale est la portée définie lors de l'étape lexicale. La portée lexicale est déterminée par l'endroit où vous écrivez les variables et les portées de bloc lorsque vous écrivez du code, tandis que la portée dynamique est déterminée par l'utilisation des variables. par l'emplacement. Regardons un exemple :

Tout d’abord, analysons combien de scopes y a-t-il au total ?
function foo(a) {
  var b = a * 2;
  function bar(c) {
    console.log(a, b, c)
  }
  bar(b * 3)
}
foo(2)

Portée globale, qui contient la variable foo
  1. La portée créée par la fonction foo, qui contient les variables a, b, bar
  2. La portée créée par la fonction bar, qui contient la variable c
  3. Ensuite, analysons le processus de recherche de variable. Lorsque le moteur exécute console.log(), il doit trouver des références aux trois variables a, b,. et c. Tout d'abord, commencez par la portée bar() la plus intérieure, le moteur ne peut pas trouver a, il recherchera donc jusqu'à la portée foo(). Il trouve a ici et arrête la recherche. Le processus de recherche est le même pour b et c. . La recherche de portée commence toujours à partir du niveau le plus interne du runtime et recherche vers l'extérieur jusqu'à ce que la première variable correspondante soit rencontrée.

Portée de la fonction

La portée de la fonction signifie que toutes les variables appartenant à cette fonction peuvent être utilisées et réutilisées dans la portée de la fonction entière. C'est ce que tout le monde sait. Nous savons. la définition, mais à quoi sert l'existence d'une portée de fonction ? Examinons ensuite les secondes de portée de la fonction.


Masquer l'implémentation interne

Masquer l'implémentation interne consiste à envelopper des variables et des fonctions dans la portée d'une fonction pour atteindre l'objectif de masquage. Pourquoi faites-vous cela ? Il existe un principe très connu dans la conception de logiciels appelé principe d'exposition minimale, qui fait référence à l'exposition du contenu nécessaire au minimum et au masquage d'autres contenus, tels que la conception API de modules ou d'objets. Utilisez la portée de la fonction pour envelopper des variables et des fonctions afin d'atteindre le principe d'exposition minimale et d'empêcher tout accès externe direct. Jetez un œil à l'exemple suivant :

Dans ce code, doSomethingElse et b doivent être privés à l'intérieur de doSomething. . Mais il est exposé, ce qui entraînera une utilisation sous des formes inattendues et produira des résultats inattendus. Une conception plus raisonnable devrait consister à cacher ces contenus privés à l'intérieur de doSomething, comme :
function doSomething(a) {
  b = a + doSomethingElse( a * 2 );
  console.log( b * 3 );
}
  
function doSomethingElse(a) {
  return a - 1;
}
var b;
doSomething( 2 ); // 15”

De cette façon, ni b ni doSomethingElse ne sont accessibles depuis l'extérieur de doSomething, mais il y aura également quelques problèmes. Premièrement, la fonction doSomething est déclarée dans la portée globale, ce qui pollue la portée globale. Deuxièmement, elle doit être exécutée via des appels explicites, donc y a-t-il quelque chose. Qu'en est-il d'une méthode qui ne pollue pas la portée et qui peut s'auto-exécuter sans l'appeler ? La réponse est une expression de fonction. Regardez l'exemple suivant :
function doSomething(a) {
  function doSomethingElse(a) {
    return a - 1;
  }
  var b;
  b = a + doSomethingElse( a * 2 );
  console.log( b * 3 );
}
doSomething( 2 );

Tout d'abord, regardons (function doSomething(){}). il est mis entre parenthèses. Appelez ensuite (function doSomething(a){})() pour transmettre la valeur, afin qu'elle puisse être auto-exécutée et ne pollue pas la portée. La communauté a défini un terme pour cet usage : IIFE. , qui signifie exécution immédiate de l'expression de fonction
(function doSomething(a) {
  function doSomethingElse(a) {
    return a - 1;
  }
  var b;
  b = a + doSomethingElse( a * 2 );
  console.log( b * 3 );
})(2)

块作用域

除JavaScript外很多编程语言都支持块作用域,尽管你可能写过很伪块作用域形式的代码,最常见的就是for循环:

for(var i=0; i<10; i++) {
  console.log(i)
}

写这段代码通常是希望变量i在循环内部使用,但是实际上i会被绑定到外部作用域中,要确保没有在作用域的其他地方意外使用i,就只能依靠自觉,这时候块级作用域就显得尤为有用,ES6改变了现状,引入了新的let、const关键字,let关键字可以将变量绑定到所在的任意作用域中,也就是let为其声明的变量隐式地创建了作用域:

for(let i=0; i<10; i++) {
  console.log(i)        
}
console.log(i) // ReferenceError

这时候i就只会在for循环的内部有效


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer