JavaScript - 运行机制,做用域,做用域链(Scope chain)

参考

https://www.jianshu.com/p/3b5f0cb59344
https://jingyan.baidu.com/article/4f34706e18745be386b56d46.html
https://www.2cto.com/kf/201401/273825.html
http://www.javashuo.com/article/p-apunkzvq-eh.htmlhtml

运行机制

JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程。即先解析(例如先进行变量、函数的声明提高),后运行。浏览器

JavaScript 运行分为两个阶段:

- 预解析
  - 全局预解析(全部变量和函数声明都会提早;同名的函数和变量函数的优先级高)
  - 函数内部预解析(全部的变量、函数和形参都会参与预解析)
    - 函数
    - 形参
    - 普通变量
- 执行

先预解析全局做用域,而后执行全局做用域中的代码,

在执行全局代码的过程当中遇到函数调用就会先进行函数预解析,而后再执行函数内代码。

1. 预解释/预处理,变量提高(Hoisting)

预解析过程:

  1. 把变量的声明提高到当前做用域的最前面,只会提高声明,不会提高赋值。
  2. 把声明式函数(JS有赋值式函数/函数表达式var f = function(){},这个不能被提高)的声明提高到当前做用域的最前面,只会提高声明,不会提高调用。
  3. 先提高var,在提高function

打印2次2。由于foo()提高到当前做用域的顶部。函数

function foo() {
    console.log('1');
};

foo();

function foo() {
    console.log('2');
};

foo();

JS解释器逐个块(一个<script>就是一个块)解释。先到第一个<script>,f1提高到全局做用域(打印哈哈)。到第二个<script>,最新的function f1的声明提高到全局做用域,固然执行最新的一个声明(打印嘎嘎)。code

<script>
        function f1() {
            console.log("哈哈");
        }

        f1();
    </script>
    <script>
        f1();

        function f1() {
            console.log("嘎嘎");
        }
    </script>

    <script>
        f1();
    </script>

// 一、-----------------------------------
var num = 10;
fun();
function fun() {
  console.log(num);
  var num = 20;
}
//二、-----------------------------------
var a = 18;
f1();
function f1() {
  var b = 9;
  console.log(a);
  console.log(b);
  var a = '123';
}
// 三、-----------------------------------
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
  var a = b = c = 9;
  console.log(a);
  console.log(b);
  console.log(c);
}

2. 做用域

在ES5以前JS没有块级做用,有函数做用域。用函数做用域能够避免多个<script>的全局变量污染。先能够认为JS通常没有块级做用域,有函数做用域。
块级做用域: "{}内部声明的变量只可以在{}内部访问到,在{}外部没法访问到其内部声明的变量"htm

3. 做用域链

当咱们在局部做用域中,访问一个变量时,系统首先会在当前做用域中寻找变量var的声明语句,如找到则直接使用。反之,则继续向上一级做用域中寻找var的声明语句,如找到则直接使用,反之,继续向上一级做用域中去寻找…直到全局做用域blog

例子,尝试注释掉每一个f的num

<script>


        var num = 10;

        function f1() {
            var num = 20;

            function f2() {
                var num = 30;

                function f3() {
                    var num = 50;
                    console.log(num);
                }

                f3();
            }

            f2();
        }

        f1();
    </script>


4. 隐式全局变量

在function里,用var定义的变量是局部变量;不用var定义的变量为隐式全局变量ip

function f1() {
            var a;//局部变量
            a = 9;
            //隐式全局变量
            b = 9;
            c = 9;
            console.log(a);//9
            console.log(b);//9
            console.log(c);//9
        }

        f1();
        console.log(c);//  9
        console.log(b);// 9
        console.log(a);//报错
相关文章
相关标签/搜索