Home  >  Article  >  Web Front-end  >  JavaScript breaks the scope prison

JavaScript breaks the scope prison

黄舟
黄舟Original
2017-02-27 14:25:11950browse

JavaScript breaks the scope prison


As a loose language, JavaScript has many jaw-dropping features (often some elusive and strange ones) Features), in this article we will introduce how to use some features of JavaScript to break the "scope prison" of conventional programming languages.

1. JavaScript declaration promotion

Many people should know that js has the characteristics of variable declaration promotion and function declaration promotion. Regardless of whether you have understood it before, see if the result of running the following code meets your expectations:

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");
}

In fact, js will scan the code in two rounds when running. In the first round, variables are initialized; in the second round, the code is executed. The second round of execution code is easy to understand, but the first round process is more vague. Specifically, the first round will do the following three things:

(1) Declare and initialize function parameters

(2) Declare local variables, including assigning anonymous functions to a local variable , but do not initialize them

(3) Declare and initialize the function

After understanding these theoretical foundations, the above code was actually "translated" by the js compiler after the first round of scanning "It became the following 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");
}

Now let’s look at the program runtime output shown in the comments. Do you think it makes sense? This is the role that js declaration promotion plays in it.

After knowing the mechanism of js declaration promotion, let’s look at the following code:

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();

The first line of the above comment indicates the first time the start() method is executed. Output, the second line represents the output of the second execution of the start() method. It can be seen that due to the existence of js declaration promotion, no error was reported when the start() method was executed twice. Let’s look at a small modification to this example:

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();

At this time, due to deferring the declaration of the a variable to another js file, the console.log(a) code is executed for the first time. An error is reported, so that subsequent js code will no longer be executed. However, the start() method is still executed normally the second time. This is why almost everywhere it is recommended that you use "js namespace" to deploy different js files. Below we use a piece of code to summarize how declaration promotion + namespace can cleverly "break the cage of 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();

This program will not report any errors, and we can access it in the first js file Any subsequent properties in the App namespace should present no problems as long as the program starting point is performed after all necessary assignments. This example successfully demonstrates how to make full use of the dynamic characteristics of the js language through reasonable design of code structure.

Readers may feel that this article is a bit of a headline. The above technique is just an "illusion" made through code layout: it seems that the previous code is accessing properties that do not exist. In fact, The order of actual execution is reasonable and correct. Then this article will introduce the real "cross-action access" technique.

2.js execution code

Everyone knows that the js language has an "eval()" method, which is a typical method of "really breaking the cage". Look at the code below:

(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);
    }
})();

After reading this code, I believe many people may not help but sigh at the wonders of js: "Can this also work?!". Yes. The test() method can be called in advance and executed normally due to the declaration promotion mechanism. The test() method accepts a code parameter. Inside the test() method, we rewrote the console.log method, modified the output format, and defined a private variable var a="bird" inside the test. At the end of the test method, we use eval to dynamically execute the code. The printing result is very magical: the browser uses the console.log method we rewrote to print out the private variable a inside the test method. This is complete scope isolation.

There are many similar methods in js, such as: eval(), setTimeout(), setInterval() and some construction methods of native objects. But there are two points to be reminded:

(1) This method will greatly reduce the execution efficiency of the program. Everyone knows that js itself is an interpreted language, and its performance is already many levels slower than compiled languages. On this basis, if we use methods such as eval to "recompile" a string code, the performance of the program will be much slower.

(2) Programming in this way will greatly increase the complexity of the code, and you will not be able to understand the code you wrote in a few minutes. This article introduces this method in the hope that readers will have a comprehensive understanding of the grammatical characteristics of js so that they can better correct and troubleshoot. This article does not recommend using the second approach in production-level code at all.

The above is the content of JavaScript breaking the scope prison. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn