JavaScript 中使用多態

使用javascript類庫函數時,常常會遇到一個函數,可使用不一樣個數的參數的狀況javascript

好比:exp(var1) exp(var1, var2)java

可是在實際編寫javascript函數時,程序員

函數不能同名,因此不多是不一樣參數個數分開寫;數組

參數個數必須符合函數的設置,因此函數聲明裏有的就必須有,不可能調用時寫少幾個;app

……函數

這個問題是困擾了好久了,一直不知道爲何?!工具

今天一早在看別人代碼,無心中居然看到了~
測試

 

原來不是在函數聲明中聲明參數個數,而是在函數裏直接接收使用那怎麼接收呢?
spa

就是 arguments 了prototype

arguments雖然不是數組,但能夠看成數組使用,下標由 0 開始,因此:

arguments[0] 表示接收的第一個參數
arguments[1] 表示接收的第二個參數
……
如此類推……

這樣就能夠實現不一樣參數調用同一個函數了~

固然,前提是函數設置了對該參數的處理方法,否則仍是白搭

順便搜索了一下arguments的介紹,一併貼出:
引用內容 引用內容
arguments 屬性
爲當前執行的 function 對象返回一個arguments 對象。

function.arguments

function 參數是當前執行函數的名稱,能夠省略。

說明
經過 arguments 屬性,函數能夠處理可變數量的參數。 arguments 對象的 length 屬性包含了傳遞給函數的參數的數目。對於arguments 對象所包含的單個參數,其訪問方法與數組中所包含的參數的訪問方法相同。

示例
下面的例子說明了 arguments 屬性的用法:

function ArgTest(){
    var i, s, numargs = arguments.length;
    s = numargs;
    if (numargs < 2)
        s += " argument was passed to ArgTest. It was ";
    else
         s += " arguments were passed to ArgTest. They were " ;
    for (i = 0; i < numargs; i++)
{
s += arguments[i] + " ";
}
return(s);
}

 

巧用arguments

    在 Javascript 的函數中有個名爲 arguments 的類數組對象。它看起來是那麼的詭異並且名不經傳,但衆多的 Javascript 庫都使用着它強大的功能。因此,它的特性須要每一個 Javascript 程序員去熟悉它。

    在每一個函數中,都有個名爲 arguments 的變量,它以相似數組的形式保存了當前調用的參數。而它實際上並非個數組,使用 typeof arguments 語句嘗試會返回「object」(對象),因此它不能像 Array 同樣使用 push 和 pop 等方法。即使如此,仍然可使用下標以及長度屬性(length)獲取它的值。

編寫靈活的函數
   雖看起來名不經傳,但的確 arguments 是很是有用的對象。好比,你可讓函數處理不定數目的參數。在 Dean Edwards 寫的 base2 庫中,有個叫 format 的函數充分發揮了這一特性:

function format(string) {
    var args = arguments;
    var pattern = new RegExp("%([1-" + arguments.length + "])", "g");
    return String(string).replace(pattern, function(match, index) {
       return args[index];
    });
};

   replace這個函數的第二個參數能夠爲一個函數,函數的第一個參數能夠爲匹配了的文本,第二個參數爲第幾個匹配的值,返回值爲要進行替換的文本

   這個函數實現了模板替換,你能夠在要動態替換的地方使用 %1 到 %9 標記,而後其他的參數就會依次替換這些地方。例如:format("And the %1 want to know whose %2 you %3", "papers", "shirt", "wear");
   上面的腳本就會返回
"And the papers want to know whose shirt you wear" 。
   在這裏須要注意的是,即使在 format 函數定義中,咱們僅定義了個名爲 string 的參數。而 Javascript 無論函數自身定義的參數數量,它都容許咱們向一個函數傳遞任意數量的參數,並將這些參數值保存到被調用函數的 arguments 對象中。

 

轉換成實際數組
   雖然 arguments 對象並非真正意義上的 Javascript 數組,可是咱們可使用數組的 slice 方法將其轉換成數組,相似下面的代碼

var args = Array.prototype.slice.call(arguments);


call(obj,當前函數使用的參數列表)

   call 方法第一個參數爲一個對象,這個傳進去的對象將調用slice函數.由於arguments不是一個數組,因此不能直接調用slice方法,因此只能使用 ''對象冒充''方法了。這樣,數組變量 args 包含了全部 arguments 對象包含的值。

 

使參數構建函數
   使用 arguments 對象可以簡短咱們編寫的 Javascript 代碼量。下面有個名爲 makeFunc 的函數,它根據你提供的函數名稱以及其餘任意數目的參數,而後返回個匿名函數。此匿名函數被調用時,合併的原先被調用的參數,並交給指定的函數運行而後返 回其返回值。

function makeFunc() {
    var args = Array.prototype.slice.call(arguments);
    var func = args.shift();
    return function() {
      return func.apply(null,   args.concat(Array.prototype.slice.call(arguments)));};
}

    arguments 有一個不可枚舉的屬性callee(不能用for in讀出,可用HasOwnProterty(name)來判斷),arguments.callee爲正被執行的 Function 對象。slice時己把當前函數指針copy了過去,因此args的第一個元素爲函數類型

    makeFunc 的第一個參數指定須要調用的函數名稱(是的,在這個簡單的例子中沒有錯誤檢查),獲取之後從 args 中刪除。makeFunc 返回一個匿名函數,它使用函數對象的(Function Object)apply 方法調用指定的函數。

    apply 方法的第一個參數指定了做用域,基本上的做用域是被調用的函數。不過這樣在這個例子中看起來會有點複雜,因此咱們將其設定成 null ;其第二個參數是個數組,它指定了其調用函數的參數。makeFunc 轉換其自身的 arguments 並鏈接匿名函數的 arguments,而後傳遞到被調用的函數。

   有種狀況就是老是要有個輸出的模板是相同的,爲了節省每次是使用上面提到的 format 函數並指定重複的參數,咱們可使用 makeFunc 這個工具。它將返回一個匿名函數,並自動生成已經指定模板後的內容:

var majorTom = makeFunc(format, "This is Major Tom to ground control. I'm %1.");
你能夠像這樣重複指定 majorTom 函數:

   majorTom("stepping through the door");
   majorTom("floating in a most peculiar way");
那麼當每次調用 majorTom 函數時,它都會使用第一個指定的參數填寫已經指定的模板。例如上述的代碼返回:

"This is Major Tom to ground control. I'm stepping through the door."
"This is Major Tom to ground control. I'm floating in a most peculiar way."

 

自引用的函數
   您可能會認爲這很酷,先別急着高興,後面還有個更大的驚喜。它(arguments)還有個其餘很是有用的屬性:callee 。arguments.callee 包含了當前調用函數的被引用對象。那麼咱們如何使用這玩意作些的事情?arguments.callee 是個很是有用的調用自身的匿名函數。

   下面有個名爲 repeat 的函數,它的參數須要個函數引用和兩個數字。第一個數字表示運行的次數,而第二個函數定義運行的間隔時間(毫秒爲單位)。下面是相關的代碼:

function repeat(fn, times, delay) {
    return function() {
        if (times-- > 0) {
            fn.apply(null, arguments);
            var args = Array.prototype.slice.call(arguments);
            var self = arguments.callee;
            setTimeout(function(){self.apply(null,args)}, delay);
        }
   };
}


   repeat 函數使用 arguments.callee 得到當前引用,保存到 self 變量後,返回個匿名函數從新運行本來被調用的函數。最後使用 setTimeout 以及配合個匿名函數實現延遲執行。

   做爲個簡單的說明,好比會在一般的腳本中,編寫下面的提供個字符串並彈出個警告框的簡單函數:

function comms(s) {
    alert(s);
}
   好了,後來我改變了個人想法。我想編寫個「特殊版本」的函數,它會重複三次運行每次間隔兩秒。那麼使用個人 repeat 函數,就能夠像這樣作到:

var somethingWrong = repeat(comms, 3, 2000);
somethingWrong("Can you hear me, major tom?");
結果就猶如預期的那樣,彈出了三次警告框每次延時兩秒。

最後,arguments 即使不會常常被用到,甚至顯得有些詭異,可是它上述的那些驚豔的功能(不只僅是這些!)值得你去了解它。

undefined ≠ null
null 是一個對象,undefined是一個屬性、方法或變量。存在null是由於對象被定義。若是對象沒有被定義,而測試它是不是null,但由於沒有被定義,它沒法測試到,並且會拋出錯誤。

if (myObject !== null && typeof(myObject) !== 'undefined') {     //若是myObject是undefined,它不能測試是否爲null,並且還會拋出錯誤 } if (typeof(myObject) !== 'undefined' && myObject !== null) {     //處理myObject的代碼 }

相關文章
相關標籤/搜索