摘要:說明中沒有真正意義上的函數(shù)重載。先看第一種辦法,通過對象來實現(xiàn)對象,是函數(shù)內(nèi)部的一個類數(shù)組對象,它里面保存著調(diào)用函數(shù)時,傳遞給函數(shù)的所有參數(shù)。
說明
JavaScript 中沒有真正意義上的函數(shù)重載。
函數(shù)重載函數(shù)名相同,函數(shù)的參數(shù)列表不同(包括參數(shù)個數(shù)和參數(shù)類型),根據(jù)參數(shù)的不同去執(zhí)行不同的操作。
我們舉個例子看看
function overload(a){ console.log("一個參數(shù)") } function overload(a,b){ console.log("兩個參數(shù)") } // 在支持重載的編程語言中,比如 java overload(1); //一個參數(shù) overload(1,2); //兩個參數(shù) // 在 JavaScript 中 overload(1); //兩個參數(shù) overload(1,2); //兩個參數(shù)
在JavaScript中,同一個作用域,出現(xiàn)兩個名字一樣的函數(shù),后面的會覆蓋前面的,所以 JavaScript 沒有真正意義的重載。
但是有各種辦法,能在 JavaScript 中模擬實現(xiàn)重載的效果。
先看第一種辦法,通過 arguments 對象來實現(xiàn)arguments 對象,是函數(shù)內(nèi)部的一個類數(shù)組對象,它里面保存著調(diào)用函數(shù)時,傳遞給函數(shù)的所有參數(shù)。
function overload () { if (arguments.length === 1) { console.log("一個參數(shù)") } if (arguments.length === 2) { console.log("兩個參數(shù)") } } overload(1); //一個參數(shù) overload(1, 2); //兩個參數(shù)
這個例子非常簡單,就是通過判斷 arguments 對象的 length 屬性來確定有幾個參數(shù),然后執(zhí)行什么操作。
但是參數(shù)少的情況下,還好,如果參數(shù)多一些,if 判斷就需要寫好多,就麻煩了。
所以,我們再來看一個經(jīng)典的例子
在看這個例子之前,我們先來看一個需求,我們有一個 users 對象,users 對象的values 屬性中存著一些名字。
一個名字由兩部分組成,空格左邊的是 first-name ,空格右邊的是 last-name,像下面這樣。
var users = { values: ["Dean Edwards", "Alex Russell", "Dean Tom"] };
我們要在 users 對象 中添加一個 find 方法,
當(dāng)不傳任何參數(shù)時, 返回整個users .values;
當(dāng)傳一個參數(shù)時,就把 first-name 跟這個參數(shù)匹配的元素返回;
當(dāng)傳兩個參數(shù)時,則把 first-name 和 last-name 都匹配的返回。
這個需求中 find方法 需要根據(jù)參數(shù)的個數(shù)不同而執(zhí)行不同的操作,下來我們通過一個 addMethod 函數(shù),來在 users 對象中添加這個 find 方法。
function addMethod (object, name, fn) { // 先把原來的object[name] 方法,保存在old中 var old = object[name]; // 重新定義 object[name] 方法 object[name] = function () { // 如果函數(shù)需要的參數(shù) 和 實際傳入的參數(shù) 的個數(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個參數(shù)
第一個:要綁定方法的對象,
第二個:綁定的方法名稱,
第三個:需要綁定的方法
這個 addMethod 函數(shù)在判斷參數(shù)個數(shù)的時候,除了用 arguments 對象,還用了函數(shù)的 length 屬性。
函數(shù)的 length 屬性,返回的是函數(shù)定義時形參的個數(shù)。
簡單說 函數(shù)的 length 是,函數(shù)需要幾個參數(shù),而 arguments.length 是調(diào)用函數(shù)時,真的給了函數(shù)幾個參數(shù)
function fn (a, b) { console.log(arguments.length) } console.log(fn.length); // 2 fn("a"); // 1
下來我們來使用這個 addMethod 函數(shù)
// 不傳參數(shù)時,返回整個values數(shù)組 function find0 () { return this.values; } // 傳一個參數(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; } // 傳兩個參數(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 對象添加處理 沒有參數(shù) 的方法 addMethod(users, "find", find0); // 給 users 對象添加處理 一個參數(shù) 的方法 addMethod(users, "find", find1); // 給 users 對象添加處理 兩個參數(shù) 的方法 addMethod(users, "find", find2); // 測試: 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ù)是利用了閉包的特性,通過變量 old 將每個函數(shù)連接了起來,讓所有的函數(shù)都留在內(nèi)存中。
每調(diào)用一次 addMethod 函數(shù),就會產(chǎn)生一個 old,形成一個閉包。
我們可以通過 console.dir(users.find) ,把 find 方法打印到控制臺看看。
上面這個例子是 jQuery 之父 John Resig 寫的,他在他的博客和他寫的書 《secrets of the JavaScript ninja》第一版中都有提到過,在書中的第4章中也有講解 Function overloading,文中的 addMethod 函數(shù) 就是書中的例子 4.15,感興趣的朋友可以去看看。
上面的例子,本質(zhì)都是在判斷參數(shù)的個數(shù),根據(jù)不同的個數(shù),執(zhí)行不同的操作,而下來舉的例子是通過判斷參數(shù)的類型,來執(zhí)行不同的操作。
我們看看 jQuery 中的 css( ) 方法。css( ) 方法返回或設(shè)置匹配的元素的一個或多個樣式屬性。
css(name|pro|[,val|fn])
我們可以看到 css( ) 方法,有5種 參數(shù)情況,其中3種是一個參數(shù),另外兩種是兩個參數(shù)。
而在只有一個參數(shù)的情況下,如果參數(shù)類型是字符串或者數(shù)組就是獲取屬性值,而如果參數(shù)是對象,就是是設(shè)置屬性值。
jQuery 的 css( ) 方法就是通過判斷參數(shù)的類型,來確定執(zhí)行什么操作。
我們來看看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 方法傳入每個屬性名,獲取樣式 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( ) 方法依賴于三個方法:
1、jQuery.access( ) 方法,這個方法可以獲取 或 設(shè)置,一個或者多個屬性值
jQuery.access( ) 方法里有這樣的代碼
// 設(shè)置多個屬性值 // 如果屬性名(key)的類型是 object,就遍歷這個對象 // 遍歷一次就調(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è)置一個值 } else if ( value !== undefined ) { ...... }
也就是這個方法,在幫 css( ) 方法判斷第一個參數(shù)是字符串還是對象的。
2、jQuery.style( ) 方法:在DOM節(jié)點上讀取或設(shè)置樣式屬性
在css( )方法中,如果有傳第二個參數(shù),也就是有要設(shè)置的屬性值時,那就會調(diào)用 jQuery.style( ) 方法設(shè)置樣式
3、jQuery.css( ) :在DOM元素上讀取DOM樣式值
這里的 jQuery.css( ) 是通過 jQuery.extend( ) 添加的方法,而我們最開始提到的 css( )方法,是通過 jQuery.fn.extend( ) 添加的方法,他們不是同一個方法。
jQuery.extend( )與 jQuery.fn.extend( )的區(qū)別
jQuery.extend( )是為jQuery類添加類方法(靜態(tài)方法),需要通過jQuery類來調(diào)用(直接使用 $.xxx 調(diào)用);重載的好處jQuery.fn.extend( )是為jQuery類添加成員數(shù)(實例方法),所有jQuery實例都可以直接調(diào)用(需要使用 $().xxx 調(diào)用)。
重載其實是把多個功能相近的函數(shù)合并為一個函數(shù),重復(fù)利用了函數(shù)名。
假如jQuery中的css( )方法不使用 重載,那么就要有5個不同的函數(shù),來完成功能,那我們就需要記住5個不同的函數(shù)名,和各個函數(shù)相對應(yīng)的參數(shù)的個數(shù)和類型,顯然就麻煩多了。
雖然 JavaScript 并沒有真正意義上的重載,但是重載的效果在JavaScript中卻非常常見,比如 數(shù)組的 splice( )方法,一個參數(shù)可以刪除,兩個參數(shù)可以刪除一部分,三個參數(shù)可以刪除完了,再添加新元素。
再比如 parseInt( )方法 ,傳入一個參數(shù),就判斷是用十六進(jìn)制解析,還是用十進(jìn)制解析,如果傳入兩個參數(shù),就用第二個參數(shù)作為數(shù)字的基數(shù),來進(jìn)行解析。
文中提到的實現(xiàn)重載效果的方法,本質(zhì)都是對參數(shù)進(jìn)行判斷,不管是判斷參數(shù)個數(shù),還是判斷參數(shù)類型,都是根據(jù)參數(shù)的不同,來決定執(zhí)行什么操作的。
雖然,重載能為我們帶來許多的便利,但是也不能濫用,不要把一些根本不相關(guān)的函數(shù)合為一個函數(shù),那樣并沒有什么意義。
參考淺談JavaScript函數(shù)重載
js如何實現(xiàn)重載
JavaScript函數(shù)重載
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/96045.html
摘要:譯者按之父巧妙地利用了閉包,實現(xiàn)了函數(shù)重載。在一個業(yè)余項目中,我寫了一個簡單的函數(shù),用于實現(xiàn)函數(shù)重載。而所謂函數(shù)重載,就是函數(shù)名稱一樣,但是輸入輸出不一樣。 譯者按: jQuery之父John Resig巧妙地利用了閉包,實現(xiàn)了JavaScript函數(shù)重載。 原文: JavaScript Method Overloading 譯者: Fundebug 為了保證可讀性,本文采用意...
摘要:支持綁定大多數(shù)的結(jié)構(gòu),包括和中引入的。枚舉支持枚舉和枚舉類。雖然還有進(jìn)一步優(yōu)化的空間,但到目前為止,它在實際應(yīng)用程序中的性能已經(jīng)被證明是完全可以接受的。 翻譯:云荒杯傾 Embind用于綁定C++函數(shù)和類到JavaScript,這樣編譯代碼就能在js中以一種很自然的方式來使用。Embind也支持從C++調(diào)JavaScript的class。 Embind支持綁定大多數(shù)C++的結(jié)構(gòu),包括C...
摘要:函數(shù)類型函數(shù)返回值類型我們可以給每個參數(shù)添加類型之后再為函數(shù)本身添加返回值類型。能夠根據(jù)返回語句自動推斷出返回值類型,所以通常可以省略它匿名函數(shù)完整函數(shù)類型完整的函數(shù)類型包含兩部分參數(shù)類型和返回值類型。 函數(shù)是 JavaScript 的第一等公民,函數(shù)在 JavaScript 中可以實現(xiàn)抽象層、模擬類、信息隱藏和模塊等等。TypeScript 在一定基礎(chǔ)上擴(kuò)展了函數(shù)的功能。 函數(shù)類型 ...
摘要:實現(xiàn)函數(shù)重載函數(shù)重載,是等編程語言中具有的一項特性,這項特性允許創(chuàng)建數(shù)項名稱相同但輸入輸出類型或個數(shù)不同的子程序,它可以簡單地稱為一個單獨功能可以執(zhí)行多項任務(wù)的能力。其它在中加入了類型,它自帶函數(shù)重載。 JavaScript實現(xiàn)函數(shù)重載 函數(shù)重載(function overloading),是 Ada、C++、C#、D、Java等編程語言中具有的一項特性,這項特性允許創(chuàng)建數(shù)項名稱相同...
摘要:例如允許的對象默認(rèn)情況下,通過使用內(nèi)置宏將核心對象和方法映射到。例如這被轉(zhuǎn)換為以下代碼類可以定義構(gòu)造函數(shù),具有超類,并且可以像在中一樣實例化。因此,它不違反原則。用于聲明該對象可以用作構(gòu)造函數(shù)。 這個工具可以將java代碼轉(zhuǎn)為js代碼,從而可以使用java編寫前端代碼 如果排版看著費勁可以下載下方html,打開html后使用google翻譯 JSweet語言規(guī)范版本:2.x(快照) 作...
閱讀 2144·2023-04-26 00:38
閱讀 1930·2021-09-07 10:17
閱讀 887·2021-09-02 15:41
閱讀 637·2021-08-30 09:45
閱讀 541·2019-08-29 17:25
閱讀 3204·2019-08-29 15:07
閱讀 2183·2019-08-29 12:52
閱讀 3734·2019-08-26 13:35