错误处理和函数对象
- *错误处理:
*函数对象:
*错误处理:
错误:程序执行过程中,发生的导致程序无法继续执行的状态
错误处理:即使程序出错,也要保证程序不退出的机制。
Error对象:在错误发生时,自动创建的封装错误信息的对象
属性:err.name: 错误类型:6种
SyntaxError:语法错误
ReferenceError:引用错误,找不到对象或变量时。
TypeError:类型错误,错误的使用了对象的方法
RangeError: 范围错误,参数超范围
EvalError: Eval错误,错误的使用了eval函数
URIError: URI错误
如何错误处理:
语法:try{
可能出错的语句;
}catch(err){//一旦出错,err中自动获得Error对象
只有出错,才执行的错误处理代码;
}[finally{
无论是否出错,都要执行的代码;通常在这里释放资源
}]
强调:1. 被try包裹的代码,执行效率会降低
所以,try应尽量少的包裹代码
2. err不能去掉
建议:能用if屏蔽的问题,优先选择if
大多数try catch都可提前预防
*笔试题:js中如何解决浏览器兼容性问题:3种
1. 不兼容的类型或方法:2种:
if else
try catch
2. 不兼容的值:短路逻辑中的||
值1||值2
IETester问题:
1. 只支持document.write输出
2. 只要出错,当前窗口不能继续使用,必须打开新窗口
3. 将网页文件拖拽到窗口内,自动加载。*错误处理中的return:
1. finally中的return,会替换try catch中的return
2. 即使finally中没有return,finally中的代码一定会在return前执行。但无法影响已确定的return结果抛出:自定义错误:
何时使用:方法定义者向方法调用者抛出使用错误
如何抛出:throw new Error(“错误消息”)
正课:
1. *函数对象
*重载
**匿名函数
**作用域和作用域链
*闭包
*函数对象:
执行环境栈:ECS,保存全局以及每个函数的执行环境的栈结构
执行环境:EC,调用函数时,创建的引用函数资源的对象
窗口一打开,默认ECS中压入一个全局EC
全局EC引用了window对象 VO
window对象中的变量都是全局变量
变量对象:VO,专门存储变量的对象函数生命周期:
定义时:仅创建一个函数对象,封装了函数的定义。不会读取函数的内容。
调用时:创建函数的EC对象压入ECS中,函数的EC对象引用了,当前函数的活动对象AO
活动对象:AO:专门保存本次函数调用时的局部变量
AO中有一个属性始终指向window对象
变量使用规则:优先在AO中找,
找不到,才去window对象找
调用后:函数的EC对象出栈,AO对象失去引用,被回收。AO对象中的局部变量一起被释放
*函数重载: overload
相同名称,不同参数列表的多个函数
在调用时,可根据传入参数的不同,动态选择对应的函数执行
虽然js语法默认不支持重载,但可用arguments对象模拟重载效果
arguments对象:调用时,自动创建并接收所有传入的参数值
类(like)数组(的)对象(object like array)
2点:1. arguments[i]:保存变量的个数
2. arguments.length:访问传入的第i个变量
何时使用:今后只要多个操作,共用同一个函数名时
***类数组对象 vs 数组对象:
类型不同:类数组对象的父类型是Object
数组对象的父类型是Array
导致类数组对象无法使用数组类型的方法
类数组对象 to Array:固定套路:
var arr=Array.prototype.slice.apply(arguments);
为什么还要定义参数:作用:2个:
1. 提示调用者,该如何传入参数
2. 简化函数定义者,在函数内使用参数值
结论:今后大部分方法依然要定义参数
只有不确定传入参数的个数时,才省略参数,用arguments
**匿名函数:定义时,不用任何变量引用的函数
何时使用:2种情况:
1. 如果一个函数只执行一次——–匿名函数自调 匿名函数自己调自己
语法: (function(参数变量){函数体;return 返回值})(参数值…);
在函数定义位置立即执行!
(function(a,b){return a-b;})(20,12);
2. 如果将一个函数作为对象交给其他函数使用时——回调
创建一个比较器函数:3种:
**1. 声明方式定义函数:**
function compare(a,b){return a-b}
***只有声明方式定义的函数才能被声明提前
***以下两种方式定义的函数,不能被提前
**2. 函数直接量方式定义:**
var compare=function(a,b){return a-b}
**3. 使用new关键字:**
var compare=new Function("a","b","return a-b");
匿名函数优点:节约内存空间
调用前和调用后,内存中不创建任何函数对象
总结:arr.sort(function(a,b){return a-b});
事件处理函数:onclick="calc(13)"
**作用域与作用域链:
作用域:
一个变量的可用范围,其实就是变量的实际存储位置
本质:EC对象的一个scope属性,引用了window或AO对。只可能是window中或AO中
window:全局作用域——全局变量
AO:函数作用域——局部变量
作用域链:以当前EC的scope属性为起点依次引用每个AO,直到window结束,形成的多级引用关系
只要在作用域链上存在的变量,当前函数都可使用。
*闭包**:
问题:全局变量 vs 局部变量
全局变量:优:反复使用,且共享使用
缺:可能随时在任意位置被篡改——全局污染
建议:尽量避免使用全局变量
局部变量:不可反复使用!方法调用完自动释放
解决:闭包:反复使用一个局部变量,且不会被污染
何时使用:想反复使用一个局部变量,且不希望被污染时,就要用闭包结构保护局部变量
如何使用:3步:
1. 定义外层函数(工厂函数)
特点:2个:
1.1 定义了受保护的局部变量
1.2. 返回一个专门操作局部变量的内部函数对象
2. 调用外层函数(工厂函数),获得返回的内部函数对象
3. 使用获得的内部函数对象,操作受保护的局部变量——唯一途径
判断闭包:3特点:
1. 内外层函数嵌套
2. 内层函数必须使用了外层函数的局部变量
3. 外层函数将内层函数返回到外部,可在外部调用
判断闭包结果:2句话:
1. 外层函数调用了几次,就有几个受保护的局部变量副本
2. 同一次外层函数调用返回的内部函数对象,操作同一个变量
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
/*定义一个函数,模拟取号机:
每次取一个数
数是连续不重复的
*/
//Step1:定义工厂函数保护局部变量
function factory(){
var n=0;//受保护的局部变量
return function(){ return ++n; }
}
//Step2: 获得返回的内部函数对象
var ccb=factory();
//ccb:function(){ return ++n; }
//Step3: 使用内部函数对象操作受保护的变量
console.log(ccb());//1
console.log(ccb());//2
n=1;
console.log(ccb());//3
var icbc=factory();
console.log(icbc());//1
console.log(icbc());//2
/*笔试题*/
function outer(){
for(var i=0,arr=[];i<3;i++){//i受保护的变量
arr[i]=function(){return i};
}//i变成了3
return arr;
}
var funs=outer(); //外层函数调用一次,只有1个i
console.log(funs[0]()); //3
console.log(funs[1]()); //3
console.log(funs[2]()); //3
</script>
</head>
<body>
</body>
</html>