Maison  >  Article  >  interface Web  >  Premier sujet JavaScript : promotion et précompilation de variables

Premier sujet JavaScript : promotion et précompilation de variables

coldplay.xixi
coldplay.xixiavant
2021-03-02 09:42:421802parcourir

Premier sujet JavaScript : promotion et précompilation de variables

Table des matières

  • Avant-propos
  • 1.
  • 2. Pré-analyse des Js
  • 3. Priorité entre les promotions
  • 4. ES6
  • Écrit à la fin

(Recommandations d'apprentissage gratuites associées :

Tutoriel vidéo Javascript)

Avant-propos

Cet article est la "Série avancée spécialisée JavaScript" 》Le premier article de la série, la série entière comprendra probablement, par exemple :

    Limitation anti-tremblement
  • Aplatissement
  • Copie profonde et superficielle
  • Déduplication de tableau
  • Tri
et autres points de connaissances spéciaux classiques. Ils sont nommés

Specialized Advanced car ils ont un "taux d'apparition" élevé à de nombreuses reprises. Afin d'éviter d'être transformés en , la "JavaScript Specialized Advanced Series" est née ! ! ! google内容搜索师

Premier sujet JavaScript : promotion et précompilation de variables

1. Phénomènes intéressants

Selon le bon sens, le code JavaScript doit être exécuté de haut en bas. une chaîne, et bien sûr vous devez déclarer un

à l'avance. Si je peux comprendre la vérité profonde, alors je lis le code suivant. 保存string类型的变量

1.1 L'ouverture j'ai pensé
var str = '123';console.log(str); // 123
Changeons la position du code et regardons-le à nouveau :

console.log(str); // undefinedvar str = '123';

Il me semble avoir trouvé un modèle !! !

Après avoir lu les deux premiers morceaux de code et mené une "réflexion approfondie", il me semble avoir trouvé le modèle, c'est-à-dire : dans la fonction après le bloc de code actuel, utiliser des variables dans la variable déclaration et initialisation

, Vous n'obtiendrez pas la valeur correcte. 之前

Premier sujet JavaScript : promotion et précompilation de variables

1.2 C'est effectivement le cas
Je suis venu ici avec la "conclusion" ci-dessus

var val = '余光';(function(){
    console.log(val); // 余光})();
Comme prévu ! , après

déclaration et initialisation des variables Jésus ne peut pas m'empêcher d'obtenir la valeur de val, je l'ai dit ! ! !

Quand j'ai vu le morceau de code suivant, j'étais déjà secoué, quelque chose devait être louche.

var val = '余光';(function(){
    console.log(val); // undefined
    var val = '测试';})();
Ps : Si vous avez des questions sur l'exécution immédiate de fonctions, vous pouvez aussi bien jeter un œil à "Compréhension approfondie des expressions de fonction JavaScript immédiatement invoquées (IIFE)" ~

Ceci. .. J'ai peur, qu'est-ce que c'est ? Qu'est-ce qui provoque ce phénomène ? Comment Js gère-t-il cela ?

Premier sujet JavaScript : promotion et précompilation de variables

2. Pré-analyse Js

Dans la portée actuelle, peu importe où la variable est déclarée, cela sera fait les coulisses Un mouvement invisible.

Remarque :

Seules les déclarations sont "déplacées" . Autrement dit, la déclaration et l'affectation sont passivement séparées à un moment donné. Et ce mouvement invisible est en réalité . Js在编译阶段的解析

Jetons un coup d'œil à un exemple classique de "Connaissez-vous JS" :

name = '余光'; // 未添加关键字(未声明),name为全局变量,,即window.name = '余光'var name; // 再次声明name,此时name未进行初始化,它的值是undefined吗?console.log(name); // ?
Le résultat est que la "vision périphérique" est imprimée avec succès, de sorte que

mouvement invisible est-ce que cela se produit pendant la pré-analyse Js (compilation).

2.1 Core : Pré-analyse
Afin de comprendre ce problème principal, nous devons vérifier que le moteur compilera d'abord le code JavaScript avant de l'interpréter. Une partie de la phase de compilation consiste à rechercher toutes les déclarations et à les associer à la portée appropriée. Les amis intéressés peuvent lire les deux articles "Objets variables en JavaScript" et "De la portée à la chaîne de portée" ~

Par conséquent, lorsque de telles choses se produisent, y compris

et 变量 Toutes les déclarations incluses seront traitées avant n'importe quel code est exécuté. Quand vous voyez 函数;, vous pourriez penser que c'est une déclaration. Mais JavaScript voit en fait cela comme deux déclarations : var a; et a = 2;. var a = 2

    La première déclaration de définition est faite lors de la phase de compilation.
  • La deuxième instruction d'affectation sera laissée en place en attendant son exécution.
C'est-à-dire que le code est écrit comme ceci :

// 我们看到的代码:var name = '余光';
Mais Js l'analysera en :

// 声明(Declaration)var name; // 声明但未初始化,所以分配 undefined// 初始化(Initialization)name = '余光'; // 初始化(赋值)
Donc, un morceau de code dans ce résumé devrait être analysé comme ceci :

var name; // 声明name提到作用域顶部,并被分配了一个undefinedname = '余光'; // 进行初始化操作console.log(name); // '余光'
2.2 Remarque : seules les déclarations sont promues

Seules les déclarations seront promues, tandis que les affectations et autres logiques de code ne prendront effet que lorsque le code sera exécuté. Il y aura donc le problème suivant : La fonction

foo();function foo(){
    console.log(name); // undefined
    var name = '余光';}
est promue et peut naturellement être exécutée normalement, mais la variable est uniquement déclarée promue.

2.3 Chaque scope sera promu
Toujours le code ci-dessus :

foo();function foo(){
    console.log(name); // undefined
    var name = '余光';}
En fait, il ressemble à ceci au moment de la compilation :

function foo(){
    var name; // 声明
    console.log(name); // undefined
    name = '余光'; // 初始化}foo(); // 函数执行

Premier sujet JavaScript : promotion et précompilation de variables

3. Priorité entre les promotions

Maintenant que nous savons que

et 变量 seront promus, comment juger entre elles. Et la priorité ? 函数

3.1 函数会被首先提升,然后才是变量

我们分析下面的代码:

foo();var foo; // 1function foo(){
    console.log('余光');}foo = function(){
    console.log('小李');}

本着函数优先提升的原则,他会被解析成这样:

function foo(){
    console.log('余光');}foo(); // 余光foo = function(){
    console.log('小李');}

注意,var foo 因为是一个重复声明,且优先级低于函数声明所以它被忽略掉了。

3.2 函数字面量不会进行函数提升

最直观的例子,就是在函数字面量前调用该函数:

foo();var foo = function(){
    console.log(1);}// TypeError: foo is not a function

这段程序中:

  1. 变量标识符foo被提升并分配给所在作用域(在这里是全局作用域),因此在执行foo()时不会导致ReferenceError(),而是会提示你 foo is not a function
  2. 然后就是执行foo,foo此时并没有赋值(注意变量被提升了)。由于对undefined值进行函数调用而导致非法操作,因此抛出TypeError异常。

四、ES6和小结

ES6新增了两个命令letconst,用来声明变量,有关它们完整的概念我会在《ES6基础系列》中总结,提起它们,是因为变量提升在它们身上不会存在

4.1 变量提升是可以规避的

let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

// var 的情况console.log(foo); // 输出undefinedvar foo = 2;// let 的情况console.log(bar); // 报错ReferenceErrorlet bar = 2;

上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。

在变量提升上,const和let一样,只在声明所在的块级作用域内有效,也不会变量提升

4.2 小结
  1. 变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部,但变量的初始化不会提升;
  2. 函数提升:函数声明可以被看作是函数的整体被提升到了代码的顶部,但函数字面量表达式并不会引发函数提升;
  3. 函数提升优先与变量提升;
  4. let和const可以有效的规避变量提升

最后提炼一下:JavaScript引擎并不总是按照代码的顺序来进行解析。在编译阶段,无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理,这个过程被称为提升。声明本身会被提升,而包括函数表达式的赋值在内的赋值操作并不会提升。

相关免费学习推荐:javascript(视频)

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