js 作用域

 script不能分割作用域,但是会对每个script标签对预编译,如代码3

代码1:

<script>
    console.log(typeof a2)//undefined
    var a2='littlebear';
    console.log(a2)//littlebear
</script>
<script>
    console.log(typeof a2)//string
    var a2=1;
    console.log(a2)//1
</script>

代码2:

<script>
    console.log(typeof a2)//undefined
    var a2='littlebear';
    console.log(a2)//littlebear

    console.log(typeof a2)//string
    var a2=1;
    console.log(a2)//1
</script>

代码3:

<script>
    console.log(typeof a)//undefined
    console.log(a)//报错,遇到<script>标签对时,会先对这一块进行预解析,下面没预解析,所以找不到声明过的a,于是报错了
</script>
<script>
    console.log(typeof a)//undefined
    var a=1;
    console.log(a)//1
</script>

第一个script标签里的a,undefined,直接输出啊,立马报错。因为在第一个script标签的时候没有发现a声明过,没声明直接使用就会报错。 第二个script标签里面的输出是我们预料之中的

得出一个结论:js的预编译,是从有顺序的,根据script标签的顺序从上到下执行的。

预编译阶段会预编译var后面的变量,函数参数、函数

例如:

<script>
    function fn(a,b){
        console.log(a)//容易上当
        var a=10;
        console.log(a)//10
    }
    fn('容易上当');
</script>

函数,函数参数,var声明的变量在一起的时候

<script>
    var a=10;
    function fn(a,b){
        console.log(a)//function a(){}   这里输出function a(){}, 不是参数a的值,哈哈
        var a=10;
        console.log(a)//10
        function a(){}
        console.log(a)//10
    }
    fn(15);
</script>

参数a会覆盖预编译变量a的默认值,如果有函数,函数会覆盖参数a的值,这个就是先后顺序而已

 return 和函数、var声明的变量在一起的时候

<script>
    function fn(){
        function a(){console.log(1)}
        return a;
        function a(){console.log(2)}
    }
    fn()();//2
</script>

由于预编译,后面的a覆盖了前面的a,所以return a的值 其实就是预编译之后a的值,预编译之后a的值就是第二个a。

 var a=10;
    function fn(){
        //预编译a 赋值undefined,内部作用域存在a这个变量,所以这里 !a 就是  !undefined,就是true,进入函数a=20;
        //但是后面的a怎么就是20呢,js没有块级作用域!! 不要小看js各种细节,够折腾的
        if (!a) {
            var a=20
        }
        console.log(a)//  这里是20 ,
    }
    fn()
  //a in window ==>true 、 !true ===》false
    if (!(a in window)) {
        var a = 1;
    }
    console.log(a)// undefined
 
原文地址:https://www.cnblogs.com/web-fusheng/p/6838875.html