JS进阶二

  • 1 变量对象:

1.全局作用域:声明的变量和函数,都是window对象的属性和函数

2.函数作用域: 函数内部声明的变量和函数,都是该函数的属性和函数

  • 2 作用域链:

1.每个{}为一层作用域;

2.访问当前作用域不存在的变量或者函数时,会逐层向上查找,直到查找到同名的变量或者函数

3.如果查找不到,会报异常。

  • 作用域查找对象都是从里向外查找,内层函数可以访问外层对象,反之不可以

  • 局部变量优于全局变量内层优于外层速度

  • with可以延长作用域链,但是延长会影响查询速度(不推荐使用)

 

 1 //目的实现点击每个按钮 弹出对一个的数字
 2 <body>
 3     <button>1</button>
 4     <button>2</button>
 5     <button>3</button>
 6     <script type="text/javascript">
 7     var btns=document.getElementsByTagName("button");
 8         for(var i=0;i<3;i++){
 9             btns[i].index=i;//给btns[i]挂上一个索引值  
10             btns[i].onclick=function(){
11                 alert(this.(index+1));
12             }
13         }
14     </script>
  • 3JS解析机制(只对var声明起作用)-预解析
  • 1.预解析,逐级解析作用域,将所有var声明的变量,函数赋值为undefined。
  • 2.预解析,如果同级作用域,有同名的变量和函数,则保留函数,丢弃变量。
  • 3.预解析,如果同级作用域,有同名的函数,则保留下面的函数,丢弃上面的函数。
  • 4.部分旧版本的浏览器无法预解析if/for作用域中的函数,所以最好将函数写在外面调用 5.函数表达式不会进行预解析,函数声明会进行预解析:
  • 4 函数声明和函数表达式   
  1. 函数声明: function test(){}
  2. 函数表达式:var test = function(){} 1.函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的。 2.以函数声明的方法定义的函数,函数可以在函数声明之前调用而函数表达式的函数只能在声明之后调用。 3.以函数声明的方法定义的函数并不是真正的声明,他们仅仅可以出现在全局中或者嵌套在其它函数中。
  3. 函数表达式和函数声明的区分: 1. 如果不声明函数名称,它肯定是表达式, 2. 如果声明了函数名称的话,如何判断是函数声明还是函数表达式呢?ECMAScript是通过上下文来区分的,如果function boo(){}是作为赋值表达式的一部分的话,那它就是一个函数表达式,如果function boo(){}被包含在一个函数体内,或者位于程序的最顶部的话,那它就是一个函数声明。

 

JS作用域问题一:有var的可以预解析,没有var申明的变量不可预解析。没有预解析就无法赋值为undefined,所以会报错
    <script>
    //问题1
    console.log(a);//undefined
    var  a=1;
    //问题2
    console.log(a);//报错 a is not defined
    a=1;
    </script>

JS作用域问题二:注意此处var a=1。把function a(){}给替换成了数字1,预解析时只留下了函数a()
打印结果:函数a() 1 1 3 3 报错
 1  <script>
 2     console.log(a);
 3     var a=1;
 4     console.log(a);
 5     function a(){
 6         console.log(2);
 7     }
 8     console.log(a);
 9     var a=3;
10     console.log(a);
11     function a(){
12         console.log(4)
13         };
14     console.log(a);
15   </script>
JS作用域问题三:不同script标签之间的声明按照script标签的顺序执行
 1  <script>
 2  //不同script标签之间的声明按照script标签的顺序执行
 3         console.log(a);   //报错
 4  </script>
 5 <script>
 6        var a=1;
 7 </script>
 8        <!--=======================================-->
 9 <script>
10      var a=1;
11 </script>
12 <script>
13      console.log(a);//正常
14 </script> 
JS作用域问题四①:
打印结果:undefined 1
1、预解析时var a = 2的值是undefined,执行代码到函数fn()时,打印a是undefined
2、执行代码到最后,虽然var = 2,但是它是局部变量,出不来,所以a打印是1
1    <script>
2        var a=1;
3        function fn(){
4            console.log(a);
5            var a=2
6        }
7        fn();
8        console.log(a);
9    </script>
JS作用域问题四②:这里的参数a都是全局变量
打印结果:1 2
分析:
1、因为函数fn()里面的a没有var声明,所以fn()执行时会向上一级找a的赋值,找到a = 1;
2、执行函数fn()后,因为var a = 1是全局变量,传参到fn()里面,只是传了a自身的地址进去,此时fn()里面的a 的地址与外面a的相同,他们是同一个变量,所以可以改变a的值为2
1 <script>
2     var a=1;
3     function fn(){
4         console.log(a);
5         a=2;
6     }
7     fn();
8     console.log(a);
9 </script>
JS作用域问题四③:参数是局部变量
打印结果:undefined 1
分析: (注意与JS作用域问题四②中区别,可以对比分析)
预解析: var a = undefined;fn(a){ }; fn()内部没有预解析;然后执行代码
1、函数fn(a)中的参数a是局部变量,相当于var声明的局部变量,fn()调用时,a的值是undefined;
注意:但是代码执行的顺序是var a = 1;再执行fn(a),这两个a是不同的,然后修改a = 2,这里修改的a是局部变量,不能把a的值传出fn()函数。
2、接上面第一点分析可知,全局变量a = 1没有改变,打印1。
1 <script>
2     var a=1;
3     function fn(a){  
4         console.log(a);//fn(a)中的a相当于局部变量a
5         a=2;
6     }
7     fn();
8     console.log(a);
9 </script>
JS作用域问题四④:传参是全局变量
打印结果: 1 1
分析: (注意与JS作用域问题四③中区别,可以对比分析,第1点中的注意也适用这里)
预解析: var a = undefined;fn(a){ }; fn()内部没有预解析;然后执行代码
1、调用函数fn(a)时,传参进来的是全局变量a = 1,所以打印a的值是1;继续执行,下面的a是funtion fn(a)中的形参,因为此时的a = 1由全局变量变成了fn()的中参数,所以a = 2只是把参数的值改变了,对全局变量a = 1没有影响。
2、接上面第一点分析可知,全局变量a = 1没有改变,打印1。
1 <script>
2     var a=1;
3     function fn(a){
4         console.log(a);
5         a=2;//此处function a=2是把参数改成了2.全局a没有变
6     }
7     fn(a);
8     console.log(a);
9 </script>

 

posted @ 2019-10-15 22:49  还有什么值得拥有  阅读(107)  评论(0)    收藏  举报