JavaScript函數重載

JavaScript實現函數重載

函數重載(function overloading),是 Ada、C++、C#、D、Java等編程語言中具備的一項特性,這項特性容許建立數項名稱相同但輸入輸出類型或個數不一樣的子程序,它能夠簡單地稱爲一個單獨功能能夠執行多項任務的能力。 維基百科-函數重載

函數重載是強類型語言的特性,雖然 js 是弱類型語言,咱們能夠經過一些方法實現函數重載。html

場景

班級中有不少學生,經過姓名要找到某個學生或多個學生時,同一個方法傳入的參數個數的不一樣去查找同窗。編程

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 = Array.prototype.slice.call(arguments).join('');
                return ~student.indexOf(fullName);
            });
    }
}

console.log(classRoom.find()); // [ '武大', '郎二', '張三', '張起靈', '李四', '王五' ]
console.log(classRoom.find('張')); // [ '張三', '張起靈' ]
console.log(classRoom.find('三')); // [ '張三' ]

第二種

使用 arguments 和閉包。app

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執行完畢後其中的oldfn仍然在被引用,這裏產生閉包。編程語言

因此在每次調用addMethod時,都有一個執行環境保存着當時的old以及fn,因此在使用find方法是能夠找到fn,實現重載。函數

須要注意的是:this

  • 這個重載適用於不一樣數量的參數,不區分類型、參數名或其它。
  • 會有一些函數調用的開銷。

其它

在 TypeScript 中加入了類型,它自帶函數重載。ts函數prototype

相關文章
相關標籤/搜索