1. 程式人生 > >JavaScript之錯誤處理,函式物件

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");