1. 程式人生 > >javaScript複習(八)物件、閉包

javaScript複習(八)物件、閉包

Function物件

Function物件:一切(引用型別)都是物件,物件是屬性的集合

undefined, number, string, boolean屬於簡單的值型別,不是物件。剩下的一切都是物件,包括函式、陣列、物件、null、new Number(10)都是物件。他們都是引用型別。

判斷一個變數是不是物件非常簡單。值型別的型別判斷用typeof,引用型別的型別判斷用instanceof。

 

1、arguments物件:

過載概念:程式中可定義多個相同函式名,不同引數列表的函式呼叫者不必區分每個函式的引數,在執行時,程式根據傳入的引數個數,自動判斷選擇哪個函式執行。

js語法不支援過載!但可用arguments物件模擬過載效果*

     arguments物件:函式物件內,自動建立的專門接收所有引數值得類陣列物件。

     arguments[i]: 獲得傳入的下標為i的引數值

     arguments.length: 獲得傳入的引數個數!

    即使定義了引數變數,arguments物件同樣會收到所有引數值

③例:function a(){

         if(arguments.length==1){

          //如果傳入一個引數,求平方

 alert(arguments[0]*arguments[0]);

}else if(arguments.length==2){

 //如果傳入兩個引數,求和

alert(arguments[0]+arguments[1])

}}a(3);a(5,5);    //輸出:9    10

 

2函式物件

        建立函式物件時:同時建立2個物件:

             函式物件:函式的定義

   作用域鏈物件:儲存了函式物件可用變數的位置的物件(棧)

                 預設第一項指向window物件

        呼叫函式時:又會建立1個新物件:

             活動物件:專門儲存區域性變數的物件

             在作用域鏈物件中追加指向活動物件的引用

        呼叫後:作用域鏈中活動物件的引用出棧

                活動物件因無人引用而釋放

                

   3匿名函式:定義時,不指定函式名的函式

      何時使用:2大用途:

       匿名函式自調:定義完,立刻執行

                       執行完立刻釋放

         何時使用:只有確定函式只執行一次時!

         如何自調:(function(引數){

函式體

   })(引數值);

         自調:定義在哪兒,就在哪兒執行,不提前

       匿名函式回撥:將函式作為物件傳遞給另一個函式

                       由另一個函式自主決定在需要時呼叫

        何時使用:只要將一個函式物件傳遞給其他方法呼叫時

        如何回撥:直接將匿名函式的宣告傳入另一個函式中。

 

   4閉包:

      問題:全域性變數和區域性變數的缺陷

全域性變數:容易全域性汙染

區域性變數:無法共享,不能長久儲存

閉包好處:即反覆使用區域性變數,又避免全域性汙染 就要用閉包

 

     解決:3步:閉包三特點:

      定義外層函式,封裝被保護的區域性變數

      定義內層函式,執行對外層函式區域性變數的操作

      外層函式返回內層函式的物件並且外層函式被呼叫,結果被儲存在全域性變數中

     

標準的閉包寫法

function outer(){           //定義外層函式

var n=1;             //封裝被儲存的區域性變數

function inner(){     //定義內層函式

return n++;}      //執行對外層函式區域性變數的操作

return inner;         //外層函式返回內層函式的物件

}

var getNum=outer();      //外層函式被呼叫

getNum();             

 

例:

function add() {         //定義外層函式

  var x = 1;             //封裝被儲存的區域性變數

  return function() {    //外層函式返回內層函式的物件,定義內層函式,兩步一起寫

    console.log(++x);  //執行對外層函式區域性變數的操作

  };

}

var num1 = add();        //外層函式返回內層函式的物件

var num2 = add();     //外層函式返回內層函式的物件

num1(); //輸出2, 

num1(); //輸出3,

num2(); //輸出2,

 

例:下面這段程式碼想要迴圈延時輸出結果 0 1 2 3 4,請問輸出結果是否正確,如果不正確請說明為什麼,並修改迴圈內的程式碼使其輸出正確結果

for (var i = 0; i < 5; ++i) {

     setTimeout(function() {

      console.log(i + " ");

  }, 100);

}

原因: js 執行環境為單執行緒,setTimeout 註冊的函式需要等到執行緒空閒時才能執行,此時 for 迴圈已經結束,i 值為 5,又因為迴圈中 setTimeout 接受的引數函式通過閉包訪問變數 i,所以 5 個定時輸出都是 5。

 

修改方法:將 setTimeout 放在立即執行函式中,將 i 值作為引數傳遞給包裹函式,建立新閉包。就會保護每個不同的i值

 

for (var i = 0; i < 5; ++i) {

   (function(i) {                   //定義外層函式

    setTimeout(function() {  //定義內層函式,並且引數i就是需要被儲存的區域性變數

      console.log(i + " ");      //對外層區域性變數進行操作

    }, 100);  //setTimeout()本身就是回撥函式,相當於外層函式返回內層函式的物件

  })(i);       //立即執行函式,屬於自己呼叫自己,就是外層函式被呼叫

}

輸出結果為: 0 1 2 3 4

 

5、 面向物件:在程式中都是用一個物件來描述現實中一個具體的東西。

          現實中的一個東西都包含屬性和功能:

             屬性:描述一個東西特點的變數,一個值

             功能:東西可以執行的操作

      什麼是物件:封裝多個數據和方法的儲存空間

      什麼是自定義物件:封裝現實中一個東西的屬性和功能的儲存空間。

現實中東西的屬性會成為物件中的屬性變數。

現實中東西的功能,會成為物件中的方法(函式)

6、 建立物件

①物件直接量

      var obj={"屬性名":值,

             ...  :  ...,

               "方法名" : function(){ ...this.屬性名... }

               }

  ② var obj=new Object(); //建立一個空物件

      obj.屬性名=值;

      obj.方法名=function(){...this.屬性名...}

 

  ③ 利用建構函式*反覆*建立*相同結構*的物件共2步:

      建構函式:描述一類物件結構的特殊函式

    第一步: 定義建構函式

  function 建構函式名|型別名(屬性引數1,.....){

             this.屬性名=屬性引數1;

             //在當前正在建立的物件中新增一個屬性名

         //賦值為屬性引數1的值

             ...

             this.方法名=function(){

                  ...this.屬性名...

             }

        }

      第二步: 利用建構函式建立物件:

        var obj=new 建構函式名|型別名(屬性值1,...);

  7、訪問物件的屬性與方法

   屬性:如何訪問屬性:2種:obj.屬性名  obj["屬性名"]

      訪問物件中不存在的屬性(訪問陣列中不存在的下標): 不會出錯,返回undefined

      強行給不存在屬性賦值,不報錯!js會自動建立同名屬性

 

      如何判斷某個物件是否包含指定成員:3種

      ①obj.hasOwnProperty("成員名")

      ② "屬性名" in 物件

如果找到,返回true,否則返回false!

      ③ 直接使用obj.屬性名作為條件:

 arr.indexOf!==undefined      

        如果不包含,返回undefind-->false

        如果包含,返回值或function-->true

        何時省略:判斷方法是否存在時,可省略!==

                  如果確定屬性值一定不是null,0,"",NaN

                  也可省略

 

方法:如何在方法中,訪問當前物件自己:

        this關鍵字:執行時,指代正在*呼叫*方法的物件

                                 (.前的物件)

        this本質是window下唯一的一個指標,指向當前正在呼叫方法的物件      

在方法內訪問當前物件自己的屬性,必須用this.屬性名

        this和定義在哪兒無關!僅和呼叫時使用的當前物件有關

        如果無主的呼叫或賦值,預設this都是window!

改變this的指向有call()、apple()和 bind(),想詳細瞭解請看我轉載的另一篇文章

 

8、JavaScript原型與原型鏈

知識較多較雜,梳理不清楚,推薦大家看我轉載的一篇文章《詳解JavaScript原型鏈》

這裡面說的提別清楚