JavaScript函式過載
JavaScript實現函式過載
函式過載 (function overloading),是 Ada、C++、C#、D、Java等程式語言中具有的一項特性,這項特性允許建立數項名稱相同但輸入輸出型別或個數不同的子程式,它可以簡單地稱為一個單獨功能可以執行多項任務的能力。維基百科-函式過載
函式過載是強型別語言的特性,雖然 js 是弱型別語言,我們可以通過一些方法實現函式過載。
場景
班級中有很多學生,通過姓名要找到某個學生或多個學生時,同一個方法傳入的引數個數的不同去查詢同學。
const classRoom = { students: ['武大', '郎二', '張三', '張起靈', '李四', '王五'], } classRoom.find(); // ['武大', '郎二', '張三', '張起靈', '李四', '王五']; classRoom.find('張'); // ['張三', '張起靈']; classRoom.find('張', '三'); // ['張三'];
find() find() find()
第一種
我們使用 arguments 和 switch 實現過載。
classRoom.find = function() { switch(arguments.length) { case 0: return this.students; case 1: return this.students.filter(student => { let surname = arguments[0]; return ~student.indexOf(surname); }); case 2: return this.students.filter(student => { let fullName = arguments.join(''); return ~student.indexOf(fullName); }); } } console.log(classRoom.find()); // [ '武大', '郎二', '張三', '張起靈', '李四', '王五' ] console.log(classRoom.find('張')); // [ '張三', '張起靈' ] console.log(classRoom.find('三')); // [ '張三' ]
第二種
使用 arguments 和閉包。
function addMethod(target, name, fn) { const old = target[name]; target[name] = function() { if (fn.length === arguments.length) { return fn.apply(this, arguments); } else if (typeof old === 'function') { return old.apply(this, arguments); } } } addMethod(classRoom, 'find', function() { return this.students; }); addMethod(classRoom, 'find', function(surname) { return this.students.filter(student => { return ~student.indexOf(surname); }); }); addMethod(classRoom, 'find', function(surname, personalName) { return this.students.filter(student => { return ~student.indexOf(surname + personalName); }); }); console.log(classRoom.find()); // [ '武大', '郎二', '張三', '張起靈', '李四', '王五' ] console.log(classRoom.find('張')); // [ '張三', '張起靈' ] console.log(classRoom.find('三')); // [ '張三' ]
呼叫addMethod
時會將匿名函式指向classRoom
中的find
,由於classRoom
是全域性變數所以addMethod
執行完畢後其中的old
、fn
仍然在被引用,這裡產生閉包。
所以在每次呼叫addMethod
時,都有一個執行環境儲存著當時的old
以及fn
,所以在使用find
方法是可以找到fn
,實現過載。
需要注意的是:
- 這個過載適用於不同數量的引數,不區分型別、引數名或其它。
- 會有一些函式呼叫的開銷。
其它
在 TypeScript 中加入了型別,它自帶函式過載。ts函式