四、JavaScript中的作用域链
例1:全局作用域与局部作用域
说明:我们所说的全局变量与和局部变量其实只是相对的
例2:全局作用域中可以不可以直接访问局部变量
答:以上情况是不允许的,原因:
1)由于作用域链不允许
2)由于JavaScript的垃圾回收机制
例3:探讨函数与函数的关系
通过观察,发现以上代码可以正常执行
例2:函数如果在函数中,那么也存在作用域关系,如下图所示
通过运行以上代码,系统会提示fn1()缺少对象,主要是由于当执行第15行后,系统会自动回收display函数所占用的内存空间,会导致调用fn1函数无法找到,所以会产生缺少对象错误。
回顾php代码,在函数内部定义函数,那么在函数外部是否可以访问呢?
例3:
通过运行以上代码,返回结果displayfn1
也就是说明我们在PHP中可以调用函数中的函数
1、深入探讨JavaScript与PHP中的作用域问题
PHP中的作用域问题:
在PHP代码运行过程中,系统首先会加载display函数,并在运行栈区中开辟一段连续的内存空间,当display函数被调用时,系统会自动在运行栈区中,开辟一段独立且平行的内存空间用于fn1的存储,由于两者处于平行独立关系,所以我可以在display调用完成后,直接调用fn1函数。
JS作用域
在JavaScript代码运行过程中,系统首先会加载display函数,并在运行栈区中开辟一段连续的内存空间,当display函数执行时,系统会自动在display函数作用域范围内继续开辟一段连续的内存空间用于保存fn1函数,由于两者处于包含关系,我们我们没办法直接在函数外直接调用fn1函数
例4:
通过观察以上代码,我们会发现,系统弹出100,原因:
2、作用域链
当我们在函数内部调用某一变量时,系统首先在当前函数中寻找var声明语句(var i),如找到则直接使用,否则继续向上一级作用域寻找,如找到,则直接使用,否则继续向上寻找,直到全局作用域,如找到,则使用,否则会在全局作用域中声明该变量,我们把这个过程就称之为作用域链
作用域链和原理图:
例5:
以上代码弹出结果为1000,原理同上。
例6:
运行结果:1000,1000
五、script代码段
1、JavaScript中script代码段执行流程:
1、读入第一个代码段
2、编译
声明变量,声明函数,语法检查,语义检查,代码优化,分析并得到代码树
3、执行
代码调用,代码执行
var i = 100;
编译过程:var i = undefined;
执行过程:i=100;
4、读入下一个代码段
5、编译
6、执行
7、……
8、结束
2、探讨代码段错误(编译错误、执行错误)的影响
例1:编译错误对当前代码段所产生的影响
通过运行发现,代码无法执行。原因:
我们知道代码执行分为两个阶段:
编译阶段与执行阶段,我们没有写圆括号,那么系统在编译过程就会产生错误,所以后面的代码与前面的代码都无法正常执行。
说明:编译错误会导致当前代码段无法执行
例2:执行错误对当前代码段的影响
运行结果:hello,报错
说明:当前代码在编译阶段没有任何异常,在运行时,首先运行第9行代码,运行到第10行时,系统找不到display函数,所以会报错(执行错误),会导致后面的word无法输出,所以可以说明:
script代码段执行错误只对当前代码后面的代码有影响,而不会影响前面代码的执行
例3:编译错误对后面代码段的影响
例4:执行错误对后面代码段的影响
通过例3与例4案例,我们可以得出以下结论,无论编译错误还是执行错误,都只对当前代码段有影响,而不会对后面的代码产生影响。
3、script代码段执行原理图:
面试题:判断当前程序的执行结果?
执行结果:
undefined,1000
说明:当函数执行到第9-10行时,系统定义全局变量i=100与声明函数,当执行到第15行,系统调用display函数,由于第11行代码执行alert(i),由于作用域链原则,系统首先会在当前作用域中寻找var声明,在第12行找到了var声明,又由于代码执行分为两个阶段编译与执行:由于函数display内在编译时会定义var i=undefined所以当执行第11行代码时,系统首先输出undefined,当执行到12行时,系统自动为变量赋值i=1000,当执行到13行时,系统自动弹出刚才已赋值的变量i=1000,所以两次结果为undefined与1000。
六、JavaScript中的数组
1、什么是数组?
答:一组数据的集合
一维数组
二维数组
多维数组
2、数组的定义
l var arr=[值1,值2,值3]; //隐式创建
l var arr=new Array(值1,值2,值3); //显示创建或直接实例化
l var array=new Array(size); //显示创建并指定数组长度
例1:通过以上三种方式创建数组
例2:如何对已定义数组进行引用
基本语法:
数组名称[索引]
例3:如何遍历输出数组数据
1)通过for循环进行遍历输出
数组拥有一个属性length,标识数组长度
运行结果:
2)通过for…in…进行遍历输出
输出结果:
例4:二维数组定义
运行结果:
例5:二维数组遍历
运行结果:
3、定义文本下标数组
例6:文本下标数组
运行结果:
弹出小美
例7:文本下标数组元素是不计入数组长度的
输出结果:当前数组中共有3个元素
IE调试工具,F12弹出,如下图
调试结果如下:
在数组中,我们的文本下标都是通过属性的形式追加到数组中,所以其不计入数组长度。
例8:遍历输出带文本下标型数组
示例代码:
运行结果:
七:作业
作业一:JavaScript中与Array数组相关的系统函数
添加数组元素:
l arrayObject.push(newelement1,newelement2,....,newelementX)
l arrayObject.unshift(newelement1,newelement2,....,newelementX)
l arrayObject.splice(index,howmany,element1,.....,elementX)
删除数组元素:
l arrayObject.pop()
l arrayObject.shift()
l arrayObject.splice(index,howmany)
数组的截取与合并:
l arrayObject.slice(start[,end])
l arrayObject.concat(arrayX,arrayX,......,arrayX)
l 返回新数组
数组的连接:
l arrayObject.join(separator)
数组的切割:
l stringObject.split(separator, howmany)
作业二:省市级联(二级联动)
北京 (海淀区,朝阳区)
广州 (天河,海珠区)