错误处理,匿名函数,闭包
来源:互联网 发布:jquery动态加载js文件 编辑:程序博客网 时间:2024/06/06 07:25
- 错误处理
Function对象
重载(overload)
作用域和作用域链
闭包(closure)错误处理: 程序出错的情况下保证程序不中断退出的机制
如何错误处理: try{ 可能出错的代码 }catch(err){ 处理错误的代码 }finally{ 无论是否出错,都要执行的代码 }var d=prompt("输入小数位数");var n=123.456; try{ console.log(n.toFixed(d)); }catch(err){ alert("小数位数无效"); //alert(err.message); }finally{//释放资源 d=null; n=null; }
其中: err: 发生错误时的错误对象 err.message: 封装了错误的信息 err.name:错误的名字 Error: 错误对象,在错误发生时自动创建的,封装错误信息的对象。 6种: SyntaxError: 语法错误 ReferenceError: 引用错误,找不到对象 RangeError: 范围错误,参数超范围 TypeError: 类型使用错误, 错误的使用了对象的属性或方法。 URIError: URI错误 EvalError: 错误的使用了Eval强调:finally中一般编写释放资源的代码 如果不需要释放资源,finally部分可省略关于性能: 问题: 放在try中的代码,即使不出错,执行效率也会降低解决: 大多数try catch都可用if else代替
为什么: 1. if else执行效率高; var d=prompt("输入小数位数"); var n=123.456;if(!isNaN(d)&&0<=d&&d<=20){ console.log(n.toFixed(d));}else{ alert("小数位数无效");} //释放资源 d=null; n=null;
不创建错误对象,节约内存空间,但,要求程序员的错误处理经验丰富
何时使用try catch:
1.如果可提前预料到错误的原因,就用if else
2.如果无法提前预料到错误的原因,就用try catch
try中仅包裹可能出错的代码
比如: 凡是用eval,都要错误处理关于try catch中的return:
/*鄙视题*/ 1. finally中有return:如果出错,返回4 如果没出错,返回3 finally中的return替换之前的return 2. finally中没有return: 如果出错,返回3,n:4 如果没出错,返回2,n:3 finally中的代码也永远执行, 但在确定return的值之后才执行 finally执行后,才return finally的代码不会影响return的结果*/ var n=1; function fun(){ try{ //n++; m++;//报错 return n; }catch(err){ n++; return n; }finally{ n++; //return n; } } alert(fun());//2 alert(n);//3 主动抛出错误: 何时抛出: 想提示别人错误的使用了自己定义的方法时 如何抛出自定义: 函数定义者抛出异常: throw new Error("错误信息")函数调用者,需要用try catch接住抛出的异常,并处理//程序员甲,函数定义者function round(num,d){//函数定义者抛出自定义错误 if(isNaN(num)||isNaN(d)){ throw new Error("num 和 d 必须是数字"); //抛出自定义错误,等效于错误 //后续代码不再执行! } return Math.round(num*Math.pow(10,d))/Math.pow(10,d); } //程序员乙,函数调用者 var num=prompt("输入数字"); var d=prompt("输入小数位数"); try{//函数调用者接住错误,并显示错误信息 alert(round(num,d)); }catch(err){ //alert(err.message); alert("必须输入数字!"); }<script> function myFunction(){ try{ var x=document.getElementById("demo").value; if(x=="") throw "empty"; if(isNaN(x)) throw "not a number"; if(x>10) throw "too high"; if(x<5) throw "too low"; }catch(err){ var y=document.getElementById("mess"); y.innerHTML="Error: " + err + ".";} }</script><h1>My First JavaScript</h1><p>Please input a number between 5 and 10:</p><input id="demo" type="text"><button type="button" onclick="myFunction()">Test Input</button><p id="mess"></p>
Function:专门封装函数定义的对象
重载(overload):相同函数名,不同参数列表的多个函数,在调用时,可根据传入参数的不同,自动挑选对应的函数执行。
为什么: 节省调用使用API的负担
强调: 没有代码重用!
何时使用: 同一件事,不同参数,决定不同的业务流程js语法不支持重载: js中两个同名的函数,后定义的会覆盖先定义的。仅有一个生效。
解决:函数中的arguments对象
arguments对象:在函数作用域内,接收所有参数值的类数组对象——长得像数组的对象
内容: 所有传入的参数值
存储: 像数组一样存储:下标访问每个参数值: arguments[i]
也有length属性,记录参数个数
参数 vs arguments:
参数:
1. 提示调用者,如何传入数据
2. 在函数内使用时,见文知意
以参数为主
arguments:
1. 在模拟重载时
2. 在不确定参数个数时
特殊情况才用arguments在普通模式中: 参数中和arguments中使用同一个值
一方修改,另一方同时变化——不合理
解决: 严格模式: 在函数内,顶部加:”use strict”;
参数变量的值和arguments无关!
类数组对象 vs []:
相同: 1. 都可用[i]访问每个元素
2. 都有length属性记录元素个数
3. 都可用for循环遍历,尽量不要用for in遍历
不同点: 1. 类型不同: [] 是 Array类型 类数组对象 是 Object类型 2. 类数组对象无法使用数组API
function checkout(){ //arguments:[0:450].length:1 //arguments:[0:"1010 1010 1010 1010",1:"123456"].length:2 //如果传入一个参数,就现金结账 if(arguments.length==1){ console.log("现金结账"); console.log("计算找零"); }else if(arguments.length==2){ //否则,如果传入2个参数,就刷卡结账 console.log("刷卡"); console.log("输密码"); console.log("签字"); } } checkout(450); checkout("1010 1010 1010 1010","123456"); function calc(){ //如果传入两个参数,就返回两值的和 if(arguments.length==2){ return arguments[0]+arguments[1]; }else if(arguments.length==1){ //否则 如果传入一个参数,就返回传入值的平方 return arguments[0]*arguments[0]; } } console.log(calc(12,35));//47 console.log(calc(13));//169
- Function
创建: 3种:- 声明:
function 函数名(参数列表){函数体;return 返回值}
比如: function compare(a,b){return a-b;}
只有声明方式创建的函数,才能被声明提前 - 直接量:
var 函数名=function(参数列表){函数体;return 返回值}
函数其实就是一个对象,函数名就是引用函数对象的变量
还说明js中的函数,也可作为参数传递给方法或其他变量
强调: 不能被声明提前 - 实例化对象:
var 函数名=new Function(“a”,”b”,”return a-b”);
- 声明:
*匿名函数:
定义时没有其他变量引用的函数
特点: 定义后立刻调用,调用后立刻释放
为什么: 调用后立刻释放,节约内存
何时使用:
1. 自调: 定义完。立刻调用!
如何自调:
var 返回值=(function(参数列表){
函数体;
return 返回值
})(参数值列表)
何时使用: 如果完成一项特定任务的代码段,仅执行一次,就要用匿名函数封装!
强调: (参数值列表)可写在括号内
var r=(function(a,b){return a+b;}(12,35));
console.log(r);
2. 回调: 将函数交给其他方法去调用 比如: arr.sort(function(a,b){return a-b}); 何时使用:如果其它函数需要一个函数作为参数时,而执行完希望立刻释放参数时,就用匿名函数作为参数。
作用域和作用域链:
作用域: 一个变量的可用范围
变量的存储位置
js:2种:
全局作用域window: 全局变量, 可反复使用,随处可访问
问题: 容易被污染
比如: 给从未声明过的变量赋值时,都会在全局创建或修改同名变量。
为什么: 凡是无主的变量或函数都是window的
比如: m=12; //假设m未声明
相当于window.m=12
函数作用域: 局部变量
存储在活动对象中,随函数调用而创建,调用后自动释放。
问题: 不可重用!
作用域链: 从当前函数的作用域AO开始,逐级继承,直到window,形成的链 式关系。 在函数中查找变量,按照从AO到window的顺序查找 如果AO有,就不用window的 如果AO没有,才去window找 vs Java作用域: 块级作用域: 比如一个分支或循环结构,也是一级作用域 Java中: for(var i=1,sum=0;i<=100;sum++,i++); 输出sum,报错! if(){var n} try{var m}catch(err){...} 一旦结构执行完,n和m都不能用 js中:没有块级作用域 以上三种情况的变量都是在window中创建, 可重复使用。
闭包:
保护一个可重用的局部变量的词法结构
为什么: 全局变量: 可重用,但易被污染
局部变量: 不可重用,
何时使用: 即可重用,又不会被污染
如何创建闭包:
1. 外层函数封装受保护的变量以及专门操作变量的内层函数
2. 外层函数将操作变量的内层函数返回到外部
3. 调用外层函数,获得内层函数的对象。
鄙视时:1. 找受保护的变量2. 同一次外层函数调用返回的内层函数,始终使用同一个受保护的局部变量3. 每调用一次外层函数,就会多创建一个受保护的变量的副本。
函数的中的变量预处理以及执行处理:
(1)关于函数内的变量情况一
document.write(b);//全局预处理结果为undefined 声明提前,值在原地 var b=3 document.write(b);//全局预处理值为3 function f(){//定义一个函数来改变b的值 var b=10;//因为已在前声明b的值为3,所以该处的赋值不对b产生影响所以b任然等于3 } document.write(b);//在调用函数前值为3 f(); document.write(b);//因为已在前声明b的值为3,所以该处的赋值不对b产生影响所以b任然为旧值等于3
(2)关于函数内的变量情况二
document.write(b);//全局预处理结果为undefined 因为声明提前,值在原地var b=3document.write(b);//全局预处理值为3function f(){//定义一个函数来改变b的值b=10;//此处为给b重新赋值,所以在调用该函数后,b的值为新值,也就是10 } document.write(b);//在调用函数前值为3 f(); document.write(b);//b=10 因为在调用该函数后,b的值为新值,也就是10
(3)关于调用函数的全局预处理及执行处理
1.声明
function 函数名(参数列表){函数体;return 返回值}
比如: function compare(a,b){return a-b;}
只有声明方式创建的函数,才能被声明提前
document.write(f);//值为4 以function 函数名(){}方式的函数在全局预处理中可以直接调用(也就是在函数前也可调用),因为 document.write(f)的结果为函数f的字符串内容function f(a) {return a+1;}//
function f(a){return a+1;}
f(9); document.write(f(9));//值为10 正常调用函数f后的新值。
2.直接量:
var 函数名=function(参数列表){函数体;return 返回值}
函数其实就是一个对象,函数名就是引用函数对象的变量
还说明js中的函数,也可作为参数传递给方法或其他变量
强调: 不能被声明提前
document.write("<br/>") //document.write(g(3));//会报错,因为此处是在函数g之前调用, // 所以以var 函数名=function(参数){}方式的函数在全局 // 预处理中值为undefined,所以调用结果会报错。 var g=function(b){ return b+2 } document.write(g(3));//5 正常调用函数 var a=1,b=2; function add(a,b){ var a=5; var b=10; c=a+b; return c; } alert(add(a,b));//15 alert(c)//15 因为c未在函数内(局部)声明则为全局的变量 alert(a)//1 alert(b)//2 var a=1,b=2; function add(a,b){ c=a+b; var a=5; var b=10; return c; } alert(add(a,b));//3 alert(c)//3 因为c未在函数内(局部)声明则为全局的变量 alert(a)//1 alert(b)//2
- 错误处理,匿名函数,闭包
- 匿名函数&闭包
- 匿名函数 & 闭包
- 匿名函数 闭包
- 闭包,匿名函数
- 匿名函数和闭包
- Scala 闭包 匿名函数
- 匿名函数中的闭包
- 闭包入门 - 匿名函数
- 匿名函数和闭包
- 匿名函数和闭包
- 匿名函数 VS 闭包
- 闭包和匿名函数
- 匿名函数与闭包
- 匿名函数和闭包
- note11闭包 匿名函数
- 匿名函数和闭包
- 匿名函数和闭包
- Google 官方应用架构的最佳实践指南
- 使用C++ AMP
- PHP常量
- Window7搭建Ftp服务器
- IO流详解(一)字符流
- 错误处理,匿名函数,闭包
- Opencv(Python) 教程-轮廓(3)轮廓的性质
- 数据转换宏
- S中设置window.location.href跳转无效
- mysql提示Packet for query is too large (1142 > 1024)解决方案
- Linux(Centos)之安装Nginx及注意事项(亲测可用)
- js获得元素文字内容
- SVN汉化以及简单的使用
- ARUA2017创新转型峰会(ATIC)启动上海