成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript中的函數(shù)重載(Function overloading)

inapt / 2157人閱讀

摘要:說(shuō)明中沒(méi)有真正意義上的函數(shù)重載。先看第一種辦法,通過(guò)對(duì)象來(lái)實(shí)現(xiàn)對(duì)象,是函數(shù)內(nèi)部的一個(gè)類(lèi)數(shù)組對(duì)象,它里面保存著調(diào)用函數(shù)時(shí),傳遞給函數(shù)的所有參數(shù)。

說(shuō)明

JavaScript 中沒(méi)有真正意義上的函數(shù)重載。

函數(shù)重載

函數(shù)名相同,函數(shù)的參數(shù)列表不同(包括參數(shù)個(gè)數(shù)和參數(shù)類(lèi)型),根據(jù)參數(shù)的不同去執(zhí)行不同的操作。

我們舉個(gè)例子看看

function overload(a){
    console.log("一個(gè)參數(shù)")
}

function overload(a,b){
    console.log("兩個(gè)參數(shù)")
}

// 在支持重載的編程語(yǔ)言中,比如 java
overload(1);         //一個(gè)參數(shù)
overload(1,2);    //兩個(gè)參數(shù)


// 在 JavaScript 中
overload(1);         //兩個(gè)參數(shù)
overload(1,2);    //兩個(gè)參數(shù)

在JavaScript中,同一個(gè)作用域,出現(xiàn)兩個(gè)名字一樣的函數(shù),后面的會(huì)覆蓋前面的,所以 JavaScript 沒(méi)有真正意義的重載。

但是有各種辦法,能在 JavaScript 中模擬實(shí)現(xiàn)重載的效果。

先看第一種辦法,通過(guò) arguments 對(duì)象來(lái)實(shí)現(xiàn)

arguments 對(duì)象,是函數(shù)內(nèi)部的一個(gè)類(lèi)數(shù)組對(duì)象,它里面保存著調(diào)用函數(shù)時(shí),傳遞給函數(shù)的所有參數(shù)。

function overload () {
  if (arguments.length === 1) {
    console.log("一個(gè)參數(shù)")
  }
  if (arguments.length === 2) {
    console.log("兩個(gè)參數(shù)")
  }
}

overload(1);      //一個(gè)參數(shù)
overload(1, 2);  //兩個(gè)參數(shù)

這個(gè)例子非常簡(jiǎn)單,就是通過(guò)判斷 arguments 對(duì)象的 length 屬性來(lái)確定有幾個(gè)參數(shù),然后執(zhí)行什么操作。

但是參數(shù)少的情況下,還好,如果參數(shù)多一些,if 判斷就需要寫(xiě)好多,就麻煩了。

所以,我們?cè)賮?lái)看一個(gè)經(jīng)典的例子
在看這個(gè)例子之前,我們先來(lái)看一個(gè)需求,我們有一個(gè) users 對(duì)象,users 對(duì)象的values 屬性中存著一些名字。
一個(gè)名字由兩部分組成,空格左邊的是 first-name ,空格右邊的是 last-name,像下面這樣。

var users = {
  values: ["Dean Edwards", "Alex Russell", "Dean Tom"]
};

我們要在 users 對(duì)象 中添加一個(gè) find 方法,

當(dāng)不傳任何參數(shù)時(shí), 返回整個(gè)users .values;
當(dāng)傳一個(gè)參數(shù)時(shí),就把 first-name 跟這個(gè)參數(shù)匹配的元素返回;
當(dāng)傳兩個(gè)參數(shù)時(shí),則把 first-name 和 last-name 都匹配的返回。

這個(gè)需求中 find方法 需要根據(jù)參數(shù)的個(gè)數(shù)不同而執(zhí)行不同的操作,下來(lái)我們通過(guò)一個(gè) addMethod 函數(shù),來(lái)在 users 對(duì)象中添加這個(gè) find 方法。

function addMethod (object, name, fn) {
  // 先把原來(lái)的object[name] 方法,保存在old中
  var old = object[name];

  // 重新定義 object[name] 方法
  object[name] = function () {
    // 如果函數(shù)需要的參數(shù) 和 實(shí)際傳入的參數(shù) 的個(gè)數(shù)相同,就直接調(diào)用fn
    if (fn.length === arguments.length) {
      return fn.apply(this, arguments);

      // 如果不相同,判斷old 是不是函數(shù),
      // 如果是就調(diào)用old,也就是剛才保存的 object[name] 方法
    } else if (typeof old === "function") {
      return old.apply(this, arguments);
    }
  }
}

addMethod 函數(shù),它接收3個(gè)參數(shù)
第一個(gè):要綁定方法的對(duì)象,
第二個(gè):綁定的方法名稱(chēng),
第三個(gè):需要綁定的方法

這個(gè) addMethod 函數(shù)在判斷參數(shù)個(gè)數(shù)的時(shí)候,除了用 arguments 對(duì)象,還用了函數(shù)的 length 屬性。

函數(shù)的 length 屬性,返回的是函數(shù)定義時(shí)形參的個(gè)數(shù)。

簡(jiǎn)單說(shuō) 函數(shù)的 length 是,函數(shù)需要幾個(gè)參數(shù),而 arguments.length 是調(diào)用函數(shù)時(shí),真的給了函數(shù)幾個(gè)參數(shù)

function fn (a, b) {
  console.log(arguments.length)
}
console.log(fn.length);  // 2
fn("a");    // 1

下來(lái)我們來(lái)使用這個(gè) addMethod 函數(shù)

// 不傳參數(shù)時(shí),返回整個(gè)values數(shù)組
function find0 () {
  return this.values;
}
// 傳一個(gè)參數(shù)時(shí),返回firstName匹配的數(shù)組元素
function find1 (firstName) {
  var ret = [];
  for (var i = 0; i < this.values.length; i++) {
    if (this.values[i].indexOf(firstName) === 0) {
      ret.push(this.values[i
      ]);
    }
  }
  return ret;
}
// 傳兩個(gè)參數(shù)時(shí),返回firstName和lastName都匹配的數(shù)組元素
function find2 (firstName, lastName) {
  var ret = [];
  for (var i = 0; i < this.values.length; i++) {
    if (this.values[i
    ] === (firstName + " " + lastName)) {
      ret.push(this.values[i
      ]);
    }
  }
  return ret;
}
// 給 users 對(duì)象添加處理 沒(méi)有參數(shù) 的方法
addMethod(users, "find", find0);

// 給 users 對(duì)象添加處理 一個(gè)參數(shù) 的方法
addMethod(users, "find", find1);

// 給 users 對(duì)象添加處理 兩個(gè)參數(shù) 的方法
addMethod(users, "find", find2);

// 測(cè)試:
console.log(users.find()); //["Dean Edwards", "Alex Russell", "Dean Tom"]
console.log(users.find("Dean")); //["Dean Edwards", "Dean Tom"]
console.log(users.find("Dean","Edwards")); //["Dean Edwards"]

addMethod 函數(shù)是利用了閉包的特性,通過(guò)變量 old 將每個(gè)函數(shù)連接了起來(lái),讓所有的函數(shù)都留在內(nèi)存中。

每調(diào)用一次 addMethod 函數(shù),就會(huì)產(chǎn)生一個(gè) old,形成一個(gè)閉包。
我們可以通過(guò) console.dir(users.find) ,把 find 方法打印到控制臺(tái)看看。

上面這個(gè)例子是 jQuery 之父 John Resig 寫(xiě)的,他在他的博客和他寫(xiě)的書(shū) 《secrets of the JavaScript ninja》第一版中都有提到過(guò),在書(shū)中的第4章中也有講解 Function overloading,文中的 addMethod 函數(shù) 就是書(shū)中的例子 4.15,感興趣的朋友可以去看看。

上面的例子,本質(zhì)都是在判斷參數(shù)的個(gè)數(shù),根據(jù)不同的個(gè)數(shù),執(zhí)行不同的操作,而下來(lái)舉的例子是通過(guò)判斷參數(shù)的類(lèi)型,來(lái)執(zhí)行不同的操作。

我們看看 jQuery 中的 css( ) 方法。
css( ) 方法返回或設(shè)置匹配的元素的一個(gè)或多個(gè)樣式屬性。

css(name|pro|[,val|fn])

我們可以看到 css( ) 方法,有5種 參數(shù)情況,其中3種是一個(gè)參數(shù),另外兩種是兩個(gè)參數(shù)。
而在只有一個(gè)參數(shù)的情況下,如果參數(shù)類(lèi)型是字符串或者數(shù)組就是獲取屬性值,而如果參數(shù)是對(duì)象,就是是設(shè)置屬性值。

jQuery 的 css( ) 方法就是通過(guò)判斷參數(shù)的類(lèi)型,來(lái)確定執(zhí)行什么操作。

我們來(lái)看看jQuery 3.3.1中的源碼

// name 表示屬性名
// value 表示屬性值
css: function( name, value ) {
    return access( this, function( elem, name, value ) {
        var styles, len,
            map = {},
            i = 0;

        // 判斷屬性名是不是數(shù)組
        // 是數(shù)組就遍歷,調(diào)用jQuery.css 方法傳入每個(gè)屬性名,獲取樣式
        if ( Array.isArray( name ) ) {
            styles = getStyles( elem );
            len = name.length;

            for ( ; i < len; i++ ) {
                map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
            }

            return map;
        }

        // 如果value 不等于 undefined 就調(diào)用jQuery.style 方法設(shè)置樣式
        // 如果value 等于 undefined 就調(diào)用jQuery.css 方法獲取樣式
        return value !== undefined ?
            jQuery.style( elem, name, value ) :
            jQuery.css( elem, name );
    }, name, value, arguments.length > 1 );
}

css( ) 方法依賴(lài)于三個(gè)方法:

1、jQuery.access( ) 方法,這個(gè)方法可以獲取 或 設(shè)置,一個(gè)或者多個(gè)屬性值

jQuery.access( ) 方法里有這樣的代碼

// 設(shè)置多個(gè)屬性值
// 如果屬性名(key)的類(lèi)型是 object,就遍歷這個(gè)對(duì)象
// 遍歷一次就調(diào)用一次 access()方法,并傳入這次的屬性名和屬性值
if ( jQuery.type( key ) === "object" ) {
    chainable = true;
    for ( i in key ) {
        jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
    }

// 設(shè)置一個(gè)值
} else if ( value !== undefined ) {
    ......
}

也就是這個(gè)方法,在幫 css( ) 方法判斷第一個(gè)參數(shù)是字符串還是對(duì)象的。

2、jQuery.style( ) 方法:在DOM節(jié)點(diǎn)上讀取或設(shè)置樣式屬性

在css( )方法中,如果有傳第二個(gè)參數(shù),也就是有要設(shè)置的屬性值時(shí),那就會(huì)調(diào)用 jQuery.style( ) 方法設(shè)置樣式

3、jQuery.css( ) :在DOM元素上讀取DOM樣式值

這里的 jQuery.css( ) 是通過(guò) jQuery.extend( ) 添加的方法,而我們最開(kāi)始提到的 css( )方法,是通過(guò) jQuery.fn.extend( ) 添加的方法,他們不是同一個(gè)方法。

jQuery.extend( )與 jQuery.fn.extend( )的區(qū)別

jQuery.extend( )是為jQuery類(lèi)添加類(lèi)方法(靜態(tài)方法),需要通過(guò)jQuery類(lèi)來(lái)調(diào)用(直接使用 $.xxx 調(diào)用);

jQuery.fn.extend( )是為jQuery類(lèi)添加成員數(shù)(實(shí)例方法),所有jQuery實(shí)例都可以直接調(diào)用(需要使用 $().xxx 調(diào)用)。

重載的好處

重載其實(shí)是把多個(gè)功能相近的函數(shù)合并為一個(gè)函數(shù),重復(fù)利用了函數(shù)名。
假如jQuery中的css( )方法不使用 重載,那么就要有5個(gè)不同的函數(shù),來(lái)完成功能,那我們就需要記住5個(gè)不同的函數(shù)名,和各個(gè)函數(shù)相對(duì)應(yīng)的參數(shù)的個(gè)數(shù)和類(lèi)型,顯然就麻煩多了。

總結(jié)

雖然 JavaScript 并沒(méi)有真正意義上的重載,但是重載的效果在JavaScript中卻非常常見(jiàn),比如 數(shù)組的 splice( )方法,一個(gè)參數(shù)可以刪除,兩個(gè)參數(shù)可以刪除一部分,三個(gè)參數(shù)可以刪除完了,再添加新元素。
再比如 parseInt( )方法 ,傳入一個(gè)參數(shù),就判斷是用十六進(jìn)制解析,還是用十進(jìn)制解析,如果傳入兩個(gè)參數(shù),就用第二個(gè)參數(shù)作為數(shù)字的基數(shù),來(lái)進(jìn)行解析。

文中提到的實(shí)現(xiàn)重載效果的方法,本質(zhì)都是對(duì)參數(shù)進(jìn)行判斷,不管是判斷參數(shù)個(gè)數(shù),還是判斷參數(shù)類(lèi)型,都是根據(jù)參數(shù)的不同,來(lái)決定執(zhí)行什么操作的。

雖然,重載能為我們帶來(lái)許多的便利,但是也不能濫用,不要把一些根本不相關(guān)的函數(shù)合為一個(gè)函數(shù),那樣并沒(méi)有什么意義。

參考

淺談JavaScript函數(shù)重載

js如何實(shí)現(xiàn)重載

JavaScript函數(shù)重載

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/96045.html

相關(guān)文章

  • JavaScript函數(shù)重載

    摘要:譯者按之父巧妙地利用了閉包,實(shí)現(xiàn)了函數(shù)重載。在一個(gè)業(yè)余項(xiàng)目中,我寫(xiě)了一個(gè)簡(jiǎn)單的函數(shù),用于實(shí)現(xiàn)函數(shù)重載。而所謂函數(shù)重載,就是函數(shù)名稱(chēng)一樣,但是輸入輸出不一樣。 譯者按: jQuery之父John Resig巧妙地利用了閉包,實(shí)現(xiàn)了JavaScript函數(shù)重載。 原文: JavaScript Method Overloading 譯者: Fundebug 為了保證可讀性,本文采用意...

    testHs 評(píng)論0 收藏0
  • Emscripten教程之C++和JavaScript綁定(三)

    摘要:支持綁定大多數(shù)的結(jié)構(gòu),包括和中引入的。枚舉支持枚舉和枚舉類(lèi)。雖然還有進(jìn)一步優(yōu)化的空間,但到目前為止,它在實(shí)際應(yīng)用程序中的性能已經(jīng)被證明是完全可以接受的。 翻譯:云荒杯傾 Embind用于綁定C++函數(shù)和類(lèi)到JavaScript,這樣編譯代碼就能在js中以一種很自然的方式來(lái)使用。Embind也支持從C++調(diào)JavaScript的class。 Embind支持綁定大多數(shù)C++的結(jié)構(gòu),包括C...

    warkiz 評(píng)論0 收藏0
  • TypeScript 初識(shí) - 函數(shù)

    摘要:函數(shù)類(lèi)型函數(shù)返回值類(lèi)型我們可以給每個(gè)參數(shù)添加類(lèi)型之后再為函數(shù)本身添加返回值類(lèi)型。能夠根據(jù)返回語(yǔ)句自動(dòng)推斷出返回值類(lèi)型,所以通??梢允÷运涿瘮?shù)完整函數(shù)類(lèi)型完整的函數(shù)類(lèi)型包含兩部分參數(shù)類(lèi)型和返回值類(lèi)型。 函數(shù)是 JavaScript 的第一等公民,函數(shù)在 JavaScript 中可以實(shí)現(xiàn)抽象層、模擬類(lèi)、信息隱藏和模塊等等。TypeScript 在一定基礎(chǔ)上擴(kuò)展了函數(shù)的功能。 函數(shù)類(lèi)型 ...

    ARGUS 評(píng)論0 收藏0
  • JavaScript函數(shù)重載

    摘要:實(shí)現(xiàn)函數(shù)重載函數(shù)重載,是等編程語(yǔ)言中具有的一項(xiàng)特性,這項(xiàng)特性允許創(chuàng)建數(shù)項(xiàng)名稱(chēng)相同但輸入輸出類(lèi)型或個(gè)數(shù)不同的子程序,它可以簡(jiǎn)單地稱(chēng)為一個(gè)單獨(dú)功能可以執(zhí)行多項(xiàng)任務(wù)的能力。其它在中加入了類(lèi)型,它自帶函數(shù)重載。 JavaScript實(shí)現(xiàn)函數(shù)重載 函數(shù)重載(function overloading),是 Ada、C++、C#、D、Java等編程語(yǔ)言中具有的一項(xiàng)特性,這項(xiàng)特性允許創(chuàng)建數(shù)項(xiàng)名稱(chēng)相同...

    SnaiLiu 評(píng)論0 收藏0
  • jsweet中英文文檔,java代碼轉(zhuǎn)js代碼

    摘要:例如允許的對(duì)象默認(rèn)情況下,通過(guò)使用內(nèi)置宏將核心對(duì)象和方法映射到。例如這被轉(zhuǎn)換為以下代碼類(lèi)可以定義構(gòu)造函數(shù),具有超類(lèi),并且可以像在中一樣實(shí)例化。因此,它不違反原則。用于聲明該對(duì)象可以用作構(gòu)造函數(shù)。 這個(gè)工具可以將java代碼轉(zhuǎn)為js代碼,從而可以使用java編寫(xiě)前端代碼 如果排版看著費(fèi)勁可以下載下方html,打開(kāi)html后使用google翻譯 JSweet語(yǔ)言規(guī)范版本:2.x(快照) 作...

    Near_Li 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<