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 函数声明和函数表达式
- 函数声明: function test(){}
- 函数表达式:var test = function(){} 1.以函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的。 2.以函数声明的方法定义的函数,函数可以在函数声明之前调用,而函数表达式的函数只能在声明之后调用。 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>

浙公网安备 33010602011771号