错误处理,匿名函数,闭包

来源:互联网 发布:jquery动态加载js文件 编辑:程序博客网 时间:2024/06/06 07:25
  1. 错误处理
  2. Function对象
    重载(overload)
    作用域和作用域链
    闭包(closure)

  3. 错误处理: 程序出错的情况下保证程序不中断退出的机制

      如何错误处理:       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;    
  1. 不创建错误对象,节约内存空间,但,要求程序员的错误处理经验丰富
    何时使用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>   
  1. Function:专门封装函数定义的对象
    重载(overload):相同函数名,不同参数列表的多个函数,在调用时,可根据传入参数的不同,自动挑选对应的函数执行。
    为什么: 节省调用使用API的负担
    强调: 没有代码重用!
    何时使用: 同一件事,不同参数,决定不同的业务流程

    js语法不支持重载: js中两个同名的函数,后定义的会覆盖先定义的。仅有一个生效。
    解决:函数中的arguments对象
    arguments对象:在函数作用域内,接收所有参数值的类数组对象——长得像数组的对象
    内容: 所有传入的参数值
    存储: 像数组一样存储:

  2. 下标访问每个参数值: arguments[i]

  3. 也有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
  1. Function
    创建: 3种:
    1. 声明:
      function 函数名(参数列表){函数体;return 返回值}
      比如: function compare(a,b){return a-b;}
      只有声明方式创建的函数,才能被声明提前
    2. 直接量:
      var 函数名=function(参数列表){函数体;return 返回值}
      函数其实就是一个对象,函数名就是引用函数对象的变量
      还说明js中的函数,也可作为参数传递给方法或其他变量
      强调: 不能被声明提前
    3. 实例化对象:
      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
原创粉丝点击