Maison  >  Article  >  interface Web  >  JavaScript brise la prison de la portée

JavaScript brise la prison de la portée

黄舟
黄舟original
2017-02-27 14:25:11950parcourir

JavaScript brise la prison de la portée


En tant que langage libre, JavaScript possède de nombreuses fonctionnalités à couper le souffle (souvent certaines insaisissables et étranges), dans cet article, nous présentera comment utiliser certaines fonctionnalités de JavaScript pour briser la « prison de portée » des langages de programmation conventionnels.

1. Promotion de déclaration JavaScript

Beaucoup de gens devraient savoir que js a les caractéristiques de promotion de déclaration de variable et de promotion de déclaration de fonction. Que vous l'ayez compris ou non auparavant, voyez si le résultat de l'exécution du code suivant répond à vos attentes :

var a=123;
//可以运行
abc();
//报错:def is not a function
def();
function abc(){
    //undefined
    console.log(a);
    var a="hello";
    //hello
    console.log(a);
}
var def=function(){
    console.log("def");
}

En fait, js scannera le code en deux tours lors de son exécution. Au premier tour, les variables sont initialisées ; au deuxième tour, le code est exécuté. Le deuxième cycle de code d'exécution est facile à comprendre, mais le processus du premier tour est plus vague. Plus précisément, le premier tour fera les trois choses suivantes :

(1) Déclarer et initialiser les paramètres de fonction

(2) Déclarer des variables locales, y compris l'attribution de fonctions anonymes à une variable locale, mais faire ne pas les initialiser

(3) Déclarer et initialiser les fonctions

Après avoir compris ces fondements théoriques, le code ci-dessus a en fait été "traduit" par le compilateur js après le premier tour d'analyse ” devient le suivant code :

var a;
a=123;
function abc(){
    //局部变量,将会取代外部的a
    var a;
    //undefined
    console.log(a);
    var a="hello";
    //hello
    console.log(a);
}
var def;
//可以运行
abc();
//报错:def is not a function
def();
var def=function(){
    console.log("def");
}

Examinons maintenant le résultat d'exécution du programme affiché dans les commentaires. Pensez-vous que cela a du sens ? C'est le rôle que joue la promotion de la déclaration js.

Après avoir connu le mécanisme de promotion de la déclaration js, regardons le code suivant :

var obj={};
function start(){
    //undefined
    //This is obj.a
    console.log(obj.a);
    //undefined
    //This is a
    console.log(a);
    //成功输出
    //成功输出
    console.log("页面执行完成");
}

start();
var a="This is a";
obj.a="This is obj.a";
start();

La première ligne du commentaire ci-dessus indique la première exécution de start() méthode La deuxième ligne représente le résultat de la deuxième exécution de la méthode start(). On peut voir qu'en raison de l'existence de la promotion de la déclaration js, aucune erreur n'a été signalée lorsque la méthode start() a été exécutée deux fois. Regardons une petite modification à cet exemple :

var obj={};
function start(){
    //undefined
    //This is obj.a
    console.log(obj.a);
    //报错
    //This is a
    console.log(a);
    //因为上一行的报错导致后续代码不执行
    //成功输出
    console.log("页面执行完成");
}

start();
/*---------------另一个js文件----------------*/
var a="This is a";
obj.a="This is obj.a";
start();

À ce stade, en raison du report de la déclaration de la variable a dans un autre fichier js, le code console.log(a ) signale une erreur, de sorte que le code js suivant ne sera plus exécuté. Cependant, la méthode start() est toujours exécutée normalement la deuxième fois. C'est pourquoi presque partout, il est recommandé d'utiliser « l'espace de noms js » pour déployer différents fichiers js. Ci-dessous, nous utilisons un morceau de code pour résumer comment la déclaration intelligente des espaces de noms promus « brise la cage de l'action » :

/*-----------------第一个js文件----------------*/
var App={};
App.first=(function(){
    function a(){
        App.second.b();
    }

    return {
        a:a
    };
})();

/*-----------------另一个js文件----------------*/
App.second=(function(){
    function b(){
        console.log("This is second.b");
    }

    return {
        b:b
    };
})();

//程序起点,输出This is second.b
App.first.a();

Ce programme ne signalera aucune erreur. Nous pouvons accéder aux propriétés ultérieures sans aucun problème. de l'espace de noms de l'application tant que le point de départ du programme est effectué après toutes les affectations nécessaires. Cet exemple montre avec succès comment utiliser pleinement les caractéristiques dynamiques du langage js grâce à une conception raisonnable de la structure du code.

Après avoir lu ceci, les lecteurs peuvent avoir l'impression que cet article fait un peu la une. La technique ci-dessus n'est qu'une "illusion" réalisée grâce à la disposition du code : il semble que le code précédent accède à des propriétés qui n'existent pas. En fait, l'ordre d'exécution effectif est raisonnable et correct. Ensuite, cet article présentera la véritable technique de « l'accès par action croisée ».

Code d'exécution 2.js

Tout le monde sait que le langage js a une méthode "eval()", qui est une méthode typique qui "casse vraiment l'effet de la cage". Regardez le code suivant :

(function(){
    var code="console.log(a)";
    //This is a bird
    test(code);

    function test(code){
        console.log=function(arg){
            console.info("This is a "+arg);
        };
        var a="bird";
        eval(code);
    }
})();

Après avoir lu ce code, je pense que beaucoup de gens ne peuvent s'empêcher de soupirer devant la merveille de js : "Est-ce que cela peut aussi fonctionner ?!". Oui. La méthode test() peut être appelée à l'avance et exécutée normalement grâce au mécanisme de promotion de déclaration. La méthode test() accepte un paramètre de code. Dans la méthode test(), nous avons réécrit la méthode console.log, modifié le format de sortie et défini une variable privée var a="bird" dans le test. A la fin de la méthode de test, nous utilisons eval pour exécuter dynamiquement le code. Le résultat de l'impression est très magique : le navigateur utilise la méthode console.log que nous avons réécrite pour imprimer la variable privée a à l'intérieur de la méthode de test. Il s’agit d’une isolation complète de la portée.

Il existe de nombreuses méthodes similaires en js, telles que : eval(), setTimeout(), setInterval() et certaines méthodes de construction d'objets natifs. Mais il y a deux points à rappeler :

(1) Cette méthode réduira considérablement l'efficacité d'exécution du programme. Tout le monde sait que js lui-même est un langage interprété et que ses performances sont déjà bien plus lentes que celles des langages compilés. Sur cette base, si nous utilisons des méthodes telles que eval pour « recompiler » un code chaîne, les performances du programme seront beaucoup plus lentes.

(2) Programmer de cette manière augmentera considérablement la complexité du code, et vous ne pourrez pas comprendre le code que vous avez écrit en quelques minutes. Cet article présente cette méthode dans l'espoir que les lecteurs auront une compréhension complète des caractéristiques grammaticales de js afin qu'ils puissent mieux corriger et dépanner. Cet article ne recommande pas du tout d’utiliser la deuxième approche dans le code au niveau de la production.

Ce qui précède est le contenu de JavaScript brisant la cage de portée. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn