JavaScript之錯誤處理,函數對象

1.*錯誤處理:

        錯誤:程序執行過程中,發生的導致程序無法繼續執行的狀態

        錯誤處理:即使程序出錯,也要保證程序不退出的機制

        Error對象:在發生錯誤時,*自動創建的封裝錯誤信息的對象

                  屬性:err.name:錯誤類型:6種

                            SyntaxError:語法錯誤

                            RefernceError: 引用錯誤,找不到對象或變量時

                            TypeError:類型錯誤,錯誤的使用了對象的*方法

                            RangeError:範圍錯誤,參數超範圍

                            EvalError:Eval錯誤

                            URIError:URI錯誤

        

         如何錯誤處理:語法:

  try{
      可能出錯的語句;
  }catch(err){
      一旦出錯,執行的錯誤處理代碼;
  }[finally{
  無論是否出錯,都要執行的代碼;  
}]
  

            強調:被try包裹的代碼,執行效率會降低;所以,try應儘量少的包裹代碼

     #筆試題:***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結果

 不報錯時:

/*筆試題:錯誤處理中的return*/
var n=1;
function fun() {
    try {
        return n;//return --等待
    } catch (err) {
        n++;
    } finally {
        n++;//2
       // return n;
    }
}
console.log(fun());//1
console.log(n);//2
報錯時:

 var n=1;
function fun() {
    try {
          m++;
        return n;//3
    } catch (err) {
        n++;
    } finally {
        n++;//3
        return n;//3
    }
}
console.log(fun());//3
console.log(n);//3

拋出:自定義錯誤:

             何時使用:方法定義者向方法調用者拋出使用錯誤

             如何拋出: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)數組(的)對象

               2點:1.arguments[i]   2.argument.length獲得個數

function calc(){
      if(arguments.length>=2){
          return arguments[0]+arguments[1];
      }else {
          return arguments[0]*arguments[0];
      }
  }
    console.log(calc(12,23));
    console.log(calc(13));
           何時使用:今後只要多個操作,公用一個函數名時,皆能使用

         ***類數組對象      vs      數組對象

             類型不同:類數組對象的父類型時Object;數組對象的父類型是Array   -->導致類數組對象無法使用數組類型的方法

           類數組對象 to Array固定套路:

               var arr=Array.prototype.slice.apply(arguments);

           爲什麼還要定義參數:作用:2個

                  1.提示調用者,改如何傳入參數

                  2.簡化函數定義,在函數內使用參數值

             結論:今後大部分方法依舊要定義參數,只有不確定傳入值個數時,才省略參數,用arguments


****匿名函數:定義時,沒有任何變量引用的函數

         何時使用:2種情況:

         1.如果一個函數只執行一次         --匿名函數自調

             語法:(function(參數變量){函數體:return 返回值})(參數值)

         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");   --ps:引號必須要加

var arr=[2,12,123,33,23,3,1];
  /*用三種方法定義比較器函數對象 */
/*  function compare(a,b){return a-b};*/
 /* var compare=function(a,b){return a-b};*/
  var compare=new Function("a","b","return a-b");
arr.sort(compare);
    console.log(arr);
     慣例寫法:回調               

arr.sort(function(a,b){return a-b;});
       匿名函數優點:節約內存空間;調用前和調用後,內存中不創建任何函數對象

       2.自調

/*自調*/
  (function(){
      alert("開始加載。。。");
  })();
     案例:運用遍歷和累加

/*定義add函數,可接受任意個數字參數,求所有數字參數的和*/
function add(){
    //遍歷arguments中每個參數值,同時聲明sum=0
    for(var i= 0,sum=0;i<arguments.length;i++){
        sum+=arguments[i];
    }
    //將當前參數值累計到sum中

    //返回sum
    return sum;
}
  console.log(add(1,2,3));
  console.log(add(1,2,3,5,2,9,7));
  console.log(add(1,2,3,8,7,5,3,2));

****作用域和作用域鏈:

        作用域:一個變量的可用範圍,其實就是變量的實際存儲位置;只能是window中或AO中

             window:全局作用域  ---全局變量

            AO:函數作用域           ---局部變量

            本質:EC對象的一個scope屬性,引用了window或AO對象

       作用域鏈:已當前EC的scope屬性爲起點依次應用每個AO,直到window結束,形成的多級引用關係;只要在作用域鏈上存在的變量,當前函數都可以使用


*****閉包:

     問題:全局變量  vs  局部變量

        全局變量:

               優:反覆使用,且共享使用

               缺:可能隨時在任意位置被篡改   --全局污染

              建議:儘量避免使用全局變量

       局部變量:特點:不可反覆使用,方法調用完自動釋放

       解決方案:閉包:反覆使用一個局部變量,且不會被污染

       何時使用:想反覆使用一個局部變量,且不希望被污染時,就要用閉包結構保護局部變量

       如何使用:3步:

        1.定義外部函數(工廠函數)

               特點:2步:

                    1.定義了受保護的局部變量

                    2.返回一個專門操作局部變量的內部函數對象

        2.調用外層函數(工廠函數),獲得返回的內部函數對象

        3.使用獲得的內部函數對象,操作受保護的局部變量      --ps:唯一途徑

//定義工廠函數保護局部變量
    function factory(){
        var n=0;//受保護局部變量
        return function (){ return ++n;}
    }
var ccb=factory();
    //ccb:function(){return ++n;}
    console.log(ccb());//使用變量
       

   判斷閉包輸出結構:

       1.找受保護的局部變量

       2.外層函數被調用幾次,就創建了幾個受保護的變量副本

       3.同一次外層函數調用返回的內層函數,總使用同一個局部變量

function fun(){
    for(var i= 0,arr=[];i<3;i++){
        arr[i]=function(){return i;}
        //i=3
    }
    return arr;
}
    var funs=fun();//外層函數調用1次,只有一個受保護的變量i=3
/*funs=[
 function(){return i;}
 function(){return i;}
 function(){return i;}
 同一次外層函數調用,返回的所有函數對象,使用相同一個受保護的局部變量
]

* */
  console.log(funs[0]());//3
  console.log(funs[1]());//3
  console.log(funs[2]());//3

 過程圖: 

      

筆試題:

/*匯率轉換:定義外層函數,創建人民幣對指定匯率的轉換器函數*/
function factory(rate){
     return function (money){ //返回一個函數對象,接收一個參數
        return (money/rate).toFixed(2);//函數體:返回money/rate,保留2位小數
    }
}
var rmb2$=factory(6.1);
console.log(rmb2$(6000));


    var rmb2euro=factory(10);
    console.log(rmb2euro(8684));

 例2:

/*getter/setter訪問器:
* 獲取或設置一個變量的值專門方法
* get變量名/set變量名
* */

     var getSalary,setSalary;//專門操作salary變量的訪問器
    function factory(){
        //保護一個局部變量salary,初始爲0
        var salary=0;
        //爲getSalary變量賦值一個函數對象
        getSalary=function(){
            //函數體:返回salary的值,前面加“¥”,後面保留兩位小數
            return "¥"+salary.toFixed(2);
        };
        //爲setSalary變量賦值函數對象,接收一個value參數
        setSalary=function(value){
            //函數體:如果value不是數字
            if(isNaN(value)){
                //則拋出異常“工作必須是數字”
                throw  new  Error("工資必須是數字");
            }else{
                //將value賦值個salary
                 salary=value;
            }
        }
    }
    factory();
    salary=5000;
    console.log(getSalary());
    setSalary(6000);
    console.log(getSalary());
    console.log(salary);
    setSalary("hello");

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章