Làm thế nào để quá tải các hàm trong javascript?


103

Phương pháp cổ điển (không js) đối với quá tải:

function myFunc(){
 //code
}

function myFunc(overloaded){
 //other code
}

Javascript sẽ không để nhiều hơn một hàm được định nghĩa với cùng một tên. Như vậy, những thứ như thế này hiển thị:

function myFunc(options){
 if(options["overloaded"]){
  //code
 }
}

Có cách giải quyết nào tốt hơn cho việc nạp chồng hàm trong javascript ngoài việc truyền một đối tượng có quá tải trong đó không?

Việc chuyển quá tải có thể nhanh chóng khiến một hàm trở nên quá dài dòng vì mỗi lần quá tải có thể xảy ra sẽ cần một câu lệnh điều kiện. Việc sử dụng các hàm để thực hiện //codebên trong các câu lệnh điều kiện đó có thể gây ra các tình huống phức tạp với phạm vi.


1
Sau đó, bạn đang nghĩ về javascript sai; nếu bạn có vấn đề với quá tải và phạm vi, có lẽ bạn nên có một cái tên phương pháp khác nhau như âm thanh như nó đang làm một công việc
joshcomley

@joshcomley - Quá tải và phạm vi yêu cầu mã để xử lý. Tôi chỉ đang cố gắng đảm bảo mã mà tôi sử dụng hiệu quả nhất có thể. Xử lý phạm vi với các cách giải quyết là ổn, nhưng ít nhất tôi muốn cố gắng sử dụng các phương pháp thực hành tốt nhất.
Travis J

Câu trả lời:


126

Có nhiều khía cạnh đối với quá tải đối số trong Javascript:

  1. Đối số biến - Bạn có thể truyền các tập đối số khác nhau (về cả kiểu và số lượng) và hàm sẽ hoạt động theo cách khớp với các đối số được truyền cho nó.

  2. Đối số mặc định - Bạn có thể xác định giá trị mặc định cho một đối số nếu nó không được truyền.

  3. Đối số được đặt tên - Thứ tự đối số trở nên không liên quan và bạn chỉ cần đặt tên cho đối số nào bạn muốn truyền cho hàm.

Dưới đây là một phần về từng loại xử lý đối số này.

Đối số biến

Vì javascript không có kiểm tra kiểu đối với các đối số hoặc số lượng đối số bắt buộc, bạn chỉ có thể có một triển khai của myFunc()nó có thể thích ứng với những đối số nào đã được chuyển cho nó bằng cách kiểm tra kiểu, sự hiện diện hoặc số lượng đối số.

jQuery thực hiện điều này mọi lúc. Bạn có thể đặt một số đối số là tùy chọn hoặc bạn có thể phân nhánh trong hàm của mình tùy thuộc vào đối số nào được truyền cho nó.

Khi thực hiện các loại quá tải này, bạn có một số kỹ thuật khác nhau có thể sử dụng:

  1. Bạn có thể kiểm tra sự hiện diện của bất kỳ đối số đã cho nào bằng cách kiểm tra xem giá trị tên đối số đã khai báo có phải là không undefined.
  2. Bạn có thể kiểm tra tổng số lượng hoặc các đối số với arguments.length.
  3. Bạn có thể kiểm tra loại của bất kỳ đối số nhất định nào.
  4. Đối với số lượng đối số thay đổi, bạn có thể sử dụng argumentsmảng giả để truy cập vào bất kỳ đối số đã cho nào arguments[i].

Dưới đây là một số ví dụ:

Hãy xem xét obj.data()phương thức của jQuery . Nó hỗ trợ bốn hình thức sử dụng khác nhau:

obj.data("key");
obj.data("key", value);
obj.data();
obj.data(object);

Mỗi một kích hoạt một hành vi khác nhau và, nếu không sử dụng hình thức nạp chồng động này, sẽ yêu cầu bốn chức năng riêng biệt.

Đây là cách người ta có thể phân biệt giữa tất cả các tùy chọn này bằng tiếng Anh và sau đó tôi sẽ kết hợp tất cả chúng trong mã:

// get the data element associated with a particular key value
obj.data("key");

Nếu đối số đầu tiên được truyền đến .data()là một chuỗi và đối số thứ hai là undefined, thì người gọi phải sử dụng biểu mẫu này.


// set the value associated with a particular key
obj.data("key", value);

Nếu đối số thứ hai không phải là không xác định, thì hãy đặt giá trị của một khóa cụ thể.


// get all keys/values
obj.data();

Nếu không có đối số nào được chuyển, thì trả về tất cả các khóa / giá trị trong một đối tượng được trả về.


// set all keys/values from the passed in object
obj.data(object);

Nếu kiểu của đối số đầu tiên là một đối tượng thuần túy, thì hãy đặt tất cả các khóa / giá trị từ đối tượng đó.


Đây là cách bạn có thể kết hợp tất cả những thứ đó trong một tập hợp logic javascript:

 // method declaration for .data()
 data: function(key, value) {
     if (arguments.length === 0) {
         // .data()
         // no args passed, return all keys/values in an object
     } else if (typeof key === "string") {
         // first arg is a string, look at type of second arg
         if (typeof value !== "undefined") {
             // .data("key", value)
             // set the value for a particular key
         } else {
             // .data("key")
             // retrieve a value for a key
         }
     } else if (typeof key === "object") {
         // .data(object)
         // set all key/value pairs from this object
     } else {
         // unsupported arguments passed
     }
 },

Chìa khóa của kỹ thuật này là đảm bảo rằng tất cả các dạng đối số mà bạn muốn chấp nhận đều có thể nhận dạng duy nhất và không bao giờ có bất kỳ sự nhầm lẫn nào về dạng mà người gọi đang sử dụng. Điều này thường yêu cầu sắp xếp các đối số một cách thích hợp và đảm bảo rằng có đủ tính duy nhất trong kiểu và vị trí của các đối số mà bạn luôn có thể biết được dạng nào đang được sử dụng.

Ví dụ: nếu bạn có một hàm nhận ba đối số chuỗi:

obj.query("firstArg", "secondArg", "thirdArg");

Bạn có thể dễ dàng đặt đối số thứ ba là tùy chọn và bạn có thể dễ dàng phát hiện điều kiện đó, nhưng bạn không thể chỉ đặt đối số thứ hai là tùy chọn bởi vì bạn không thể biết đối số nào trong số này có nghĩa là đang chuyển vì không có cách nào để xác định xem đối số thứ hai đối số có nghĩa là đối số thứ hai hoặc đối số thứ hai đã bị bỏ qua vì vậy những gì ở vị trí của đối số thứ hai thực sự là đối số thứ ba:

obj.query("firstArg", "secondArg");
obj.query("firstArg", "thirdArg");

Vì cả ba đối số là cùng một kiểu, bạn không thể phân biệt được sự khác biệt giữa các đối số khác nhau, do đó bạn không biết người gọi có ý định gì. Với kiểu gọi này, chỉ có thể tùy chọn đối số thứ ba. Nếu bạn muốn bỏ qua đối số thứ hai, thay vào đó nó sẽ phải được chuyển dưới dạng null(hoặc một số giá trị có thể phát hiện khác) và mã của bạn sẽ phát hiện ra rằng:

obj.query("firstArg", null, "thirdArg");

Đây là một ví dụ jQuery về các đối số tùy chọn. cả hai đối số là tùy chọn và nhận giá trị mặc định nếu không được truyền:

clone: function( dataAndEvents, deepDataAndEvents ) {
    dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
    deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

    return this.map( function () {
        return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
    });
},

Đây là một ví dụ về jQuery trong đó đối số có thể bị thiếu hoặc bất kỳ một trong ba kiểu khác nhau cung cấp cho bạn bốn trạng thái quá tải khác nhau:

html: function( value ) {
    if ( value === undefined ) {
        return this[0] && this[0].nodeType === 1 ?
            this[0].innerHTML.replace(rinlinejQuery, "") :
            null;

    // See if we can take a shortcut and just use innerHTML
    } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
        (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
        !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

        value = value.replace(rxhtmlTag, "<$1></$2>");

        try {
            for ( var i = 0, l = this.length; i < l; i++ ) {
                // Remove element nodes and prevent memory leaks
                if ( this[i].nodeType === 1 ) {
                    jQuery.cleanData( this[i].getElementsByTagName("*") );
                    this[i].innerHTML = value;
                }
            }

        // If using innerHTML throws an exception, use the fallback method
        } catch(e) {
            this.empty().append( value );
        }

    } else if ( jQuery.isFunction( value ) ) {
        this.each(function(i){
            var self = jQuery( this );

            self.html( value.call(this, i, self.html()) );
        });

    } else {
        this.empty().append( value );
    }

    return this;
},

Đối số được đặt tên

Các ngôn ngữ khác (như Python) cho phép một người truyền các đối số được đặt tên như một phương tiện chỉ truyền một số đối số và làm cho các đối số độc lập với thứ tự chúng được truyền vào. Javascript không hỗ trợ trực tiếp tính năng của các đối số được đặt tên. Một mẫu thiết kế thường được sử dụng ở vị trí của nó là truyền một bản đồ các thuộc tính / giá trị. Điều này có thể được thực hiện bằng cách truyền một đối tượng có thuộc tính và giá trị hoặc trong ES6 trở lên, bạn thực sự có thể truyền chính đối tượng Bản đồ.

Đây là một ví dụ đơn giản về ES5:

jQuery's $.ajax()chấp nhận một dạng sử dụng trong đó bạn chỉ cần truyền cho nó một tham số duy nhất là một đối tượng Javascript thông thường với các thuộc tính và giá trị. Thuộc tính nào bạn chuyển nó sẽ xác định đối số / tùy chọn nào đang được chuyển đến lệnh gọi ajax. Một số có thể được yêu cầu, nhiều là tùy chọn. Vì chúng là các thuộc tính trên một đối tượng nên không có thứ tự cụ thể. Trên thực tế, có hơn 30 thuộc tính khác nhau có thể được truyền cho đối tượng đó, chỉ một (url) là bắt buộc.

Đây là một ví dụ:

$.ajax({url: "http://www.example.com/somepath", data: myArgs, dataType: "json"}).then(function(result) {
    // process result here
});

Bên trong quá trình $.ajax()thực thi, nó có thể chỉ thẩm vấn các thuộc tính nào đã được chuyển cho đối tượng đến và sử dụng chúng làm đối số được đặt tên. Điều này có thể được thực hiện với for (prop in obj)hoặc bằng cách nhận tất cả các thuộc tính vào một mảng với Object.keys(obj)và sau đó lặp lại mảng đó.

Kỹ thuật này được sử dụng rất phổ biến trong Javascript khi có số lượng lớn các đối số và / hoặc nhiều đối số là tùy chọn. Lưu ý: điều này thúc đẩy hàm triển khai để đảm bảo rằng có một tập hợp các đối số hợp lệ tối thiểu và cung cấp cho người gọi một số phản hồi gỡ lỗi bị thiếu nếu không đủ đối số được truyền (có thể bằng cách ném một ngoại lệ với thông báo lỗi hữu ích) .

Trong môi trường ES6, có thể sử dụng hàm hủy để tạo các thuộc tính / giá trị mặc định cho đối tượng được truyền ở trên. Điều này được thảo luận chi tiết hơn trong bài viết tham khảo này .

Đây là một ví dụ từ bài báo đó:

function selectEntries({ start=0, end=-1, step=1 } = {}) {
    ···
};

Điều này tạo ra các thuộc tính và giá trị mặc định cho start, endstepcác thuộc tính trên một đối tượng được truyền cho selectEntries()hàm.

Giá trị mặc định cho các đối số của hàm

Trong ES6, Javascript bổ sung hỗ trợ ngôn ngữ tích hợp cho các giá trị mặc định cho các đối số.

Ví dụ:

function multiply(a, b = 1) {
  return a*b;
}

multiply(5); // 5

Mô tả thêm về các cách này có thể được sử dụng tại đây trên MDN .


Vì vậy, tôi chỉ nên gắn bó với một chức năng thích ứng và chấp nhận đó là phương pháp tốt nhất để thực hiện mặt tiền quá tải chức năng?
Travis J

2
@TravisJ - vâng, hàm có thể thích ứng là cách thực hiện quá tải trong Javascript. Tùy chọn khác của bạn là sử dụng một hàm được đặt tên riêng với các đối số khác nhau. Nếu hai cách triển khai không có điểm chung, thì một trong hai cách thực hiện có thể chấp nhận được. Nếu hai triển khai về cơ bản thực hiện cùng một việc, nhưng chỉ bắt đầu với các đối số khác nhau, thì tôi nghĩ rằng nó làm cho giao diện của bạn nhỏ gọn hơn để sử dụng chức năng thích ứng và nó cho bạn cơ hội chia sẻ mã giữa hai triển khai có liên quan.
jfriend00

Đã thêm một số ví dụ về mã, được giải thích bằng cả tiếng Anh và mã thực tế.
jfriend00

Tôi gặp lỗi, mã thông báo không mong muốn '=' trên phiên bản Safari mới nhất khi tôi thử điều này resetProgressBar: function(display_errors, lockout = false).
Nick,

@Nick - Theo bảng tương thích ES6 này , các giá trị tham số mặc định sẽ hoạt động trong Safari 10 trở lên. Mỗi trang MDN này , nó nói "không hỗ trợ" trong Safari. Tôi không có máy Mac nên không thể tự mình kiểm tra. Có vẻ như nó thường là một trong những tính năng ES6 được triển khai sau này trên nhiều trình duyệt. Ví dụ: có vẻ như nó chưa có trong iOS9.
jfriend00 19/07/2016

33

Việc ghi đè một hàm trong JavaScript có thể được thực hiện theo nhiều cách. Tất cả chúng đều liên quan đến một chức năng chính duy nhất thực hiện tất cả các quy trình hoặc ủy quyền cho các chức năng / quy trình con.

Một trong những kỹ thuật đơn giản phổ biến nhất liên quan đến một công tắc đơn giản:

function foo(a, b) {
    switch (arguments.length) {
    case 0:
        //do basic code
        break;
    case 1:
        //do code with `a`
        break;
    case 2:
    default:
        //do code with `a` & `b`
        break;
    }
}

Một kỹ thuật thanh lịch hơn sẽ là sử dụng một mảng (hoặc đối tượng nếu bạn không tạo quá tải cho mọi số đối số):

fooArr = [
    function () {
    },
    function (a) {
    },
    function (a,b) {
    }
];
function foo(a, b) {
    return fooArr[arguments.length](a, b);
}

Ví dụ trước đó không đẹp lắm, bất kỳ ai cũng có thể sửa đổi fooArrvà sẽ không thành công nếu ai đó chuyển hơn 2 đối số vào foo, vì vậy, một biểu mẫu tốt hơn sẽ là sử dụng một mẫu mô-đun và một vài lần kiểm tra:

var foo = (function () {
    var fns;
    fns = [
        function () {
        },
        function (a) {
        },
        function (a, b) {
        }
    ];
    function foo(a, b) {
        var fnIndex;
        fnIndex = arguments.length;
        if (fnIndex > foo.length) {
            fnIndex = foo.length;
        }
        return fns[fnIndex].call(this, a, b);
    }
    return foo;
}());

Tất nhiên, quá tải của bạn có thể muốn sử dụng một số tham số động, vì vậy bạn có thể sử dụng một đối tượng cho fnsbộ sưu tập.

var foo = (function () {
    var fns;
    fns = {};
    fns[0] = function () {
    };
    fns[1] = function (a) {
    };
    fns[2] = function (a, b) {
    };
    fns.params = function (a, b /*, params */) {
    };
    function foo(a, b) {
        var fnIndex;
        fnIndex = arguments.length;
        if (fnIndex > foo.length) {
            fnIndex = 'params';
        }
        return fns[fnIndex].apply(this, Array.prototype.slice.call(arguments));
    }
    return foo;
}());

Sở thích cá nhân của tôi có xu hướng là switch, mặc dù nó làm tăng số lượng lớn chức năng chính. Một ví dụ phổ biến về nơi tôi sử dụng kỹ thuật này sẽ là một phương thức truy cập / bộ đột biến:

function Foo() {} //constructor
Foo.prototype = {
    bar: function (val) {
        switch (arguments.length) {
        case 0:
            return this._bar;
        case 1:
            this._bar = val;
            return this;
        }
    }
}

Đây là một ví dụ tốt đẹp của một sự thay thế :)
Travis J

1
Thật tuyệt, tôi thích kỹ thuật thứ 2 đó
Nick Rolando

8

Bạn không thể làm quá tải phương thức theo nghĩa chặt chẽ. Không giống như cách nó được hỗ trợ trong javahoặc c#.

Vấn đề là JavaScript KHÔNG hỗ trợ tính năng nạp chồng phương thức. Vì vậy, nếu nó thấy / phân tích cú pháp hai hoặc nhiều hàm có cùng tên, nó sẽ chỉ xem xét hàm được xác định cuối cùng và ghi đè lên các hàm trước đó.

Một trong những cách tôi nghĩ phù hợp với hầu hết các trường hợp là sau:

Hãy nói rằng bạn có phương pháp

function foo(x)
{
} 

Thay vì nạp chồng phương thức không thể thực hiện được trong javascript, bạn có thể xác định một phương thức mới

fooNew(x,y,z)
{
}

và sau đó sửa đổi chức năng thứ nhất như sau:

function foo(x)
{
  if(arguments.length==2)
  {
     return fooNew(arguments[0],  arguments[1]);
  }
} 

Nếu bạn có nhiều phương thức quá tải như vậy, hãy xem xét sử dụng switchhơn là chỉ sử dụng các if-elsecâu lệnh.

( chi tiết hơn ) Tái bút: Liên kết trên đi đến blog cá nhân của tôi có thêm chi tiết về điều này.


Đó không phải là một vấn đề, đó là một tính năng.
inetphantom

4

Tôi đang sử dụng phương pháp nạp chồng hơi khác dựa trên số đối số. Tuy nhiên, tôi tin rằng cách tiếp cận của John Fawcett cũng tốt. Đây là ví dụ, mã dựa trên giải thích của John Resig (Tác giả của jQuery).

// o = existing object, n = function name, f = function.
    function overload(o, n, f){
        var old = o[n];
        o[n] = function(){
            if(f.length == arguments.length){
                return f.apply(this, arguments);
            }
            else if(typeof o == 'function'){
                return old.apply(this, arguments);
            }
        };
    }

khả năng sử dụng:

var obj = {};
overload(obj, 'function_name', function(){ /* what we will do if no args passed? */});
overload(obj, 'function_name', function(first){ /* what we will do if 1 arg passed? */});
overload(obj, 'function_name', function(first, second){ /* what we will do if 2 args passed? */});
overload(obj, 'function_name', function(first,second,third){ /* what we will do if 3 args passed? */});
//... etc :)

4

Trong javascript, bạn có thể triển khai hàm chỉ một lần và gọi hàm mà không cần tham số myFunc() Sau đó, bạn kiểm tra xem các tùy chọn có là 'không xác định' không

function myFunc(options){
 if(typeof options != 'undefined'){
  //code
 }
}

3

Tôi đã cố gắng phát triển một giải pháp thanh lịch cho vấn đề này được mô tả ở đây . Và bạn có thể tìm thấy bản demo ở đây . Cách sử dụng trông như thế này:

var out = def({
    'int': function(a) {
        alert('Here is int '+a);
    },

    'float': function(a) {
        alert('Here is float '+a);
    },

    'string': function(a) {
        alert('Here is string '+a);
    },

    'int,string': function(a, b) {
        alert('Here is an int '+a+' and a string '+b);
    },
    'default': function(obj) {
        alert('Here is some other value '+ obj);
    }

});

out('ten');
out(1);
out(2, 'robot');
out(2.5);
out(true);

Các phương pháp được sử dụng để đạt được điều này:

var def = function(functions, parent) {
 return function() {
    var types = [];
    var args = [];
    eachArg(arguments, function(i, elem) {
        args.push(elem);
        types.push(whatis(elem));
    });
    if(functions.hasOwnProperty(types.join())) {
        return functions[types.join()].apply(parent, args);
    } else {
        if (typeof functions === 'function')
            return functions.apply(parent, args);
        if (functions.hasOwnProperty('default'))
            return functions['default'].apply(parent, args);        
    }
  };
};

var eachArg = function(args, fn) {
 var i = 0;
 while (args.hasOwnProperty(i)) {
    if(fn !== undefined)
        fn(i, args[i]);
    i++;
 }
 return i-1;
};

var whatis = function(val) {

 if(val === undefined)
    return 'undefined';
 if(val === null)
    return 'null';

 var type = typeof val;

 if(type === 'object') {
    if(val.hasOwnProperty('length') && val.hasOwnProperty('push'))
        return 'array';
    if(val.hasOwnProperty('getDate') && val.hasOwnProperty('toLocaleTimeString'))
        return 'date';
    if(val.hasOwnProperty('toExponential'))
        type = 'number';
    if(val.hasOwnProperty('substring') && val.hasOwnProperty('length'))
        return 'string';
 }

 if(type === 'number') {
    if(val.toString().indexOf('.') > 0)
        return 'float';
    else
        return 'int';
 }

 return type;
};

1
Một chức năng để xử lý các đầu vào, rất thông minh.
Travis J

3

https://github.com/jrf0110/leFunc

var getItems = leFunc({
  "string": function(id){
    // Do something
  },
  "string,object": function(id, options){
    // Do something else
  },
  "string,object,function": function(id, options, callback){
    // Do something different
    callback();
  },
  "object,string,function": function(options, message, callback){
    // Do something ca-raaaaazzzy
    callback();
  }
});

getItems("123abc"); // Calls the first function - "string"
getItems("123abc", {poop: true}); // Calls the second function - "string,object"
getItems("123abc", {butt: true}, function(){}); // Calls the third function - "string,object,function"
getItems({butt: true}, "What what?" function(){}); // Calls the fourth function - "object,string,function"

3

Không có vấn đề với quá tải trong JS, pb làm thế nào để duy trì một mã sạch khi chức năng quá tải?

Bạn có thể sử dụng chuyển tiếp để có mã rõ ràng, dựa trên hai điều:

  1. Số đối số (khi gọi hàm).
  2. Loại đối số (khi gọi hàm)

      function myFunc(){
          return window['myFunc_'+arguments.length+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments);
       }
    
        /** one argument & this argument is string */
      function myFunc_1_string(){
    
      }
       //------------
       /** one argument & this argument is object */
      function myFunc_1_object(){
    
      }
      //----------
      /** two arguments & those arguments are both string */
      function myFunc_2_string_string(){
    
      }
       //--------
      /** Three arguments & those arguments are : id(number),name(string), callback(function) */
      function myFunc_3_number_string_function(){
                let args=arguments;
                  new Person(args[0],args[1]).onReady(args[3]);
      }
    
       //--- And so on ....   


2

Vì JavaScript không có chức năng tùy chọn quá tải đối tượng có thể được sử dụng thay thế. Nếu có một hoặc hai đối số bắt buộc, tốt hơn nên giữ chúng tách biệt với đối tượng tùy chọn. Dưới đây là một ví dụ về cách sử dụng đối tượng tùy chọn và các giá trị được điền vào giá trị mặc định trong trường hợp nếu giá trị không được chuyển vào đối tượng tùy chọn.

function optionsObjectTest(x, y, opts) {
    opts = opts || {}; // default to an empty options object

    var stringValue = opts.stringValue || "string default value";
    var boolValue = !!opts.boolValue; // coerces value to boolean with a double negation pattern
    var numericValue = opts.numericValue === undefined ? 123 : opts.numericValue;

    return "{x:" + x + ", y:" + y + ", stringValue:'" + stringValue + "', boolValue:" + boolValue + ", numericValue:" + numericValue + "}";

}

đây là một ví dụ về cách sử dụng đối tượng tùy chọn


2

Đối với điều này, bạn cần tạo một hàm bổ sung hàm vào một đối tượng, sau đó nó sẽ thực thi tùy thuộc vào số lượng đối số bạn gửi đến hàm:

<script > 
//Main function to add the methods
function addMethod(object, name, fn) {
  var old = object[name];
  object[name] = function(){
    if (fn.length == arguments.length)
      return fn.apply(this, arguments)
    else if (typeof old == 'function')
      return old.apply(this, arguments);
  };
}


  var ninjas = {
   values: ["Dean Edwards", "Sam Stephenson", "Alex Russell"]
};

//Here we declare the first function with no arguments passed
  addMethod(ninjas, "find", function(){
    return this.values;
});

//Second function with one argument
  addMethod(ninjas, "find", function(name){
    var ret = [];
    for (var i = 0; i < this.values.length; i++)
      if (this.values[i].indexOf(name) == 0)
        ret.push(this.values[i]);
    return ret;
  });

//Third function with two arguments
  addMethod(ninjas, "find", function(first, last){
    var ret = [];
    for (var i = 0; i < this.values.length; i++)
      if (this.values[i] == (first + " " + last))
        ret.push(this.values[i]);
    return ret;
  });


//Now you can do:
ninjas.find();
ninjas.find("Sam");
ninjas.find("Dean", "Edwards")
</script>

0

Tôi muốn thêm các hàm con trong một hàm mẹ để đạt được khả năng phân biệt giữa các nhóm đối số cho cùng một chức năng.

var doSomething = function() {
    var foo;
    var bar;
};

doSomething.withArgSet1 = function(arg0, arg1) {
    var obj = new doSomething();
    // do something the first way
    return obj;
};

doSomething.withArgSet2 = function(arg2, arg3) {
    var obj = new doSomething();
    // do something the second way
    return obj;
};

0

Điều bạn đang cố gắng đạt được tốt nhất nên được thực hiện bằng cách sử dụng biến đối số cục bộ của hàm.

function foo() {
    if (arguments.length === 0) {
        //do something
    }
    if (arguments.length === 1) {
        //do something else
    }
}

foo(); //do something
foo('one'); //do something else

Bạn có thể tìm thấy lời giải thích tốt hơn về cách hoạt động của điều này tại đây .


Và những gì về phát hiện va chạm? Đây là một cách hay để sử dụng các hàm không tham số hoặc để kiểm tra sự tồn tại, nhưng không thực sự là cách tốt nhất khi nói đến quá tải.
Travis J
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.