全局预处理与执行,作用域与作用域链

Posted foreverwaiting

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全局预处理与执行,作用域与作用域链相关的知识,希望对你有一定的参考价值。

一.全局预处理

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <p>全局预处理:首先会创建一个词法环境(Lexical Environment),然后扫面全局里用var声明的变量和
        用声明的方式创建的函数即function xxx(){代码段}</p>
    <p>函数表达式即var q=function(){代码段}</p>
    <p>扫描后把变量存入写成 a:undefined  把函数写成 xxx:指向函数或对函数的一个引用</p>
    <script>
        alert(a);
        alert(b);
        alert(c);
        alert(f);
        //alert(d);//此处d弹出报错d为未定义undefined,影响后续,故注释掉
        var a=1;
        var b;
        d=5;
        alert(d);
        function f(){
            console.log(‘ff‘);
        }
        var c=function (){//此时由于使用函数表达式创建的函数,所以可以当作用var声明的变量
            console.log(‘ccc‘);
        }
    </script>
</body>
</html>

二.全局预处理与执行

 

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <p>js会从上往下扫描解读js代码</p>
    <p>预处理扫描阶段:先扫描var=a变量并js解析器储存为a:undefined,和声明的函数存为d:指向函数的引用。此时扫描完后即几个alert都
        弹出过后,遇到var a=1;则此时将先前存的undefined改为值1</p>
    <p>执行阶段:与预处理不同,直接扫描到c=2就直接存入显示c:2</p>
    <script>
        alert(a);
        alert(b);//在c处会因扫描不到报错未定义而停止,故将其先注释
        //alert(c);
        alert(d);
        alert(e);
        var a=1;
        var b;
        c=2;
        alert(c);
        function d(){
            console.log(‘ddd‘);
        }
        var e=function(){
            consolu.log(‘eee‘);
        }
    </script>
</body>
</html>

 

三.函数预处理与执行

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <p>对于函数的预处理与执行:首先会扫描函数的参数,再函数内部声明式函数,再内部var变量</p>
    <p>所以下面的首先词法环境会存入参数a:1,b:2(因为参数已经传入所以先扫描存入参数,若形参两个为ab,而实参传入一个
        则第二个参数值为undefined) </p>
    <p>之后预处理,则函数内部声明的函数命名与之前的参数冲突,函数覆盖,故此时a由值1变为指向函数的引用,同时内
        部var声明的变量也有冲突为忽略,则b值依旧为2</p>
    <p>预处理结束后执行阶段:此时弹出的a为函数的引用,b为2</p>
    <script>
        function f(a,b){
            alert(a);
            alert(b);
            var b=100;
            function a(){
                console.log(‘gggg‘);
            }
        }
        f(1,2);
    </script>
</body>
</html>

四.变量与函数命名冲突

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <p>函数为第一优先级,碰到函数命名与其他有冲突会覆盖,碰到变量与其他有冲突会忽略</p>
    <script>
        alert(a);
        var a=1;//此处处理变量和函数冲突与前后顺序无关,均为函数优先
        function a(){
            console.log(‘fff‘);
        }
        function a(){//处理两函数冲突则后者函数会覆盖函数
            console.log(‘ggg‘);
        }
    </script>
</body>
</html>

五.作用域

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <p>js不是块作用域,也无动态作用域,js是词法作用域也可称为静态作用域或者闭包</p>
    <p>创建函数时给函数添加一个成员scope</p>
    <script>
        var x=10;
        function ff(){//(js解析器从上到下解析时)给函数添加一个scope==创建函数时的词法环境==window
            alert(x);//此处解析出要弹出一个变量x,而ff函数未定义x,所以去其scope找也未找到再去window找,
            // window全局也没有,所以此时报错,改进方法为添加全局变量var x=10;即可
        }
        function ff1(){
            var x=9;
            ff();//在此处掉用函数执行时创建一个自己的词法环境  与  scope关联起来(而scope==window)
        }
        function ff2(){
            var x=8;
            ff();
        }
        ff1();//改进后弹出10
    </script>
</body>
</html>

六.作用域链

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <script>
        function f(){//f在js解析器从上到下解析时创建的scope(作用域) == window
            //f被调用时创建自己的词法环境(Lexical Environment)  与  f的scope(作用域)关联起来
            var x=10;//把x=10加入f的Lx中
            function g(){//创建函数g时的scope(作用域) == f的词法环境(Lx),即创建时预处理会把变量和函数都加入f的此法环境中
           //g运行时g会创建自己的词法环境(Lx)== g的scope(作用域)
            }
            g();//调用g函数
        }
        //作用域链为 :g(Lx)-->g[scope]-->f(Lx)-->f[scope]-->window
    </script>
</body>
</html>

七.有关new Function

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <p>创建函数的方式</p>
    <p>第一:function f(){代码段}。常用</p>
    <p>第二:var g = function (){代码段}。常用</p>
    <p>另第二:var g = function f(argument){代码段}。此处f访问不到不常用</p>
    <p>第三:var g = new Function ("参数","函数体")</p>
    <p>像之前所说的作用域链,用new Function创建的函数作用域永远指向全局,而不是父函数</p>
    <script>
        //第一种情况
        function f(){
            var x=10;
            var g=function (){
                alert(x);
            }
            g();
        }
        f();//由于作用域链原因最终结果弹出10
        //第二种情况
//        var x=100;
//        function f (){
//            var x=10;
//            var g = new Function ("","alert(x)");
//            g();
//        }
//        f();//由于用new Function创建的函数作用域永远指向全局,而不是父函数,故只有在全局声明x才能弹出值
    </script>
</body>
</html>

 

以上是关于全局预处理与执行,作用域与作用域链的主要内容,如果未能解决你的问题,请参考以下文章

作用域与作用域链

JavaScript的作用域与作用域链

JavaScript-作用域与作用域链

js函数3-作用域与作用域链

作用域与作用域链

作用域与作用域链