JavaScript'te işlevler nasıl aşırı yüklenir?


104

Aşırı yüklemeye klasik (js olmayan) yaklaşım:

function myFunc(){
 //code
}

function myFunc(overloaded){
 //other code
}

Javascript, aynı adla birden fazla işlevin tanımlanmasına izin vermez. Bu nedenle, bunun gibi şeyler ortaya çıkıyor:

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

Javascript'te işlev aşırı yüklemesi için, içinde aşırı yük olan bir nesneyi iletmekten başka daha iyi bir çözüm var mı?

Aşırı yüklemeleri geçmek, bir işlevin hızlı bir şekilde çok ayrıntılı olmasına neden olabilir, çünkü her olası aşırı yük, bir koşullu ifadeye ihtiyaç duyar. //codeBu koşullu ifadelerin içini gerçekleştirmek için işlevleri kullanmak , kapsamlarla ilgili zor durumlara neden olabilir.


1
O zaman javascript'i yanlış düşünüyorsunuz; Aşırı yüklemeler ve kapsam ile ilgili sorunlarınız varsa, muhtemelen başka bir iş yapıyormuş gibi göründüğü için farklı bir yöntem ismine sahip olmalısınız
joshcomley

@joshcomley - Aşırı yükler ve kapsam, işlemek için kod gerektirir. Yalnızca kullandığım kodun olabildiğince verimli olmasını sağlamaya çalışıyorum. Kapsamların geçici çözümlerle kullanılması iyi bir şey, ancak en azından en iyi uygulama yöntemlerini kullanmayı tercih ediyorum.
Travis J

Yanıtlar:


126

Javascript'te argüman aşırı yüklemesinin birçok yönü vardır:

  1. Değişken bağımsız değişkenler - Farklı bağımsız değişken kümeleri (hem tür hem de miktar olarak) iletebilirsiniz ve işlev, kendisine iletilen bağımsız değişkenlerle eşleşen bir şekilde davranır.

  2. Varsayılan bağımsız değişkenler - Aktarılmamışsa bir bağımsız değişken için varsayılan bir değer tanımlayabilirsiniz.

  3. Adlandırılmış bağımsız değişkenler - Bağımsız değişken sırası önemsiz hale gelir ve yalnızca işleve iletmek istediğiniz bağımsız değişkenleri adlandırırsınız.

Aşağıda, bu argüman işleme kategorilerinin her biri hakkında bir bölüm bulunmaktadır.

Değişken Argümanlar

JavaScript'in bağımsız değişkenler üzerinde tür denetimi veya gerekli bağımsız değişken sayısı olmadığından, yalnızca bir uygulamanız olabilir. myFunc() olmadığından, bağımsız değişkenlerin türünü, varlığını veya miktarını kontrol ederek kendisine iletilen bağımsız değişkenlere uyum sağlayabilen sahip olabilirsiniz.

jQuery bunu her zaman yapar. Bazı bağımsız değişkenleri isteğe bağlı yapabilir veya kendisine iletilen bağımsız değişkenlere bağlı olarak işlevinizde dallara ayrılabilirsiniz.

Bu tür aşırı yüklemeleri uygularken, kullanabileceğiniz birkaç farklı tekniğiniz vardır:

  1. Belirtilen bağımsız değişken adı değerinin olup olmadığını kontrol ederek herhangi bir bağımsız değişkenin varlığını kontrol edebilirsiniz undefined.
  2. Toplam miktarı veya argümanları ile kontrol edebilirsiniz arguments.length.
  3. Herhangi bir argümanın türünü kontrol edebilirsiniz.
  4. Değişken sayıdaki bağımsız değişkenler için, argumentsherhangi bir bağımsız değişkene erişmek için sözde diziyi kullanabilirsiniz arguments[i].

İşte bazı örnekler:

JQuery'nin obj.data()yöntemine bakalım . Dört farklı kullanım biçimini destekler:

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

Her biri farklı bir davranışı tetikler ve bu dinamik aşırı yükleme biçimini kullanmadan dört ayrı işlev gerektirir.

İşte tüm bu seçenekleri İngilizce'de nasıl ayırt edebileceğiniz ve sonra hepsini kodda birleştireceğim:

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

Aktarılan ilk bağımsız değişken .data()bir dizeyse ve ikinci bağımsız değişken ise undefined, arayanın bu formu kullanıyor olması gerekir.


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

İkinci bağımsız değişken tanımsız değilse, belirli bir anahtarın değerini ayarlayın.


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

Hiçbir bağımsız değişken iletilmezse, döndürülen bir nesnedeki tüm anahtarları / değerleri döndürür.


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

İlk bağımsız değişkenin türü düz bir nesneyse, o nesneden tüm anahtarları / değerleri ayarlayın.


Tüm bunları tek bir javascript mantığı kümesinde nasıl birleştirebileceğiniz aşağıda açıklanmıştır:

 // 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
     }
 },

Bu tekniğin anahtarı, kabul etmek istediğiniz tüm argüman biçimlerinin benzersiz bir şekilde tanımlanabilir olduğundan ve arayanın hangi formu kullandığı konusunda hiçbir zaman kafa karışıklığı olmadığından emin olmaktır. Bu genellikle argümanların uygun şekilde sıralanmasını ve hangi formun kullanıldığını her zaman anlayabileceğiniz argümanların türü ve konumunda yeterli benzersizlik olduğundan emin olmayı gerektirir.

Örneğin, üç dize argümanı alan bir işleviniz varsa:

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

Üçüncü argümanı kolayca isteğe bağlı hale getirebilir ve bu koşulu kolayca tespit edebilirsiniz, ancak yalnızca ikinci argümanı isteğe bağlı yapamazsınız çünkü arayanın hangisinin geçeceğini söyleyemezsiniz çünkü ikinci argümanı tanımlamanın bir yolu yoktur. argüman, ikinci argüman anlamına gelir veya ikinci argüman ihmal edildi, bu nedenle ikinci argümanın yerinde olan aslında üçüncü argümandır:

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

Üç bağımsız değişken de aynı türde olduğundan, farklı bağımsız değişkenler arasındaki farkı söyleyemezsiniz, böylece arayanın ne istediğini bilemezsiniz. Bu çağrı stiliyle, yalnızca üçüncü argüman isteğe bağlı olabilir. İkinci bağımsız değişkeni atlamak isterseniz, bunun nullyerine (veya başka bir algılanabilir değer) olarak iletilmesi gerekir ve kodunuz şunu algılar:

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

İsteğe bağlı bağımsız değişkenlerin bir jQuery örneğini burada bulabilirsiniz. her iki bağımsız değişken de isteğe bağlıdır ve geçirilmezse varsayılan değerleri alır:

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

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

İşte bağımsız değişkenin eksik olabileceği bir jQuery örneği veya size dört farklı aşırı yükleme sağlayan üç farklı türden herhangi biri:

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;
},

Adlandırılmış Bağımsız Değişkenler

Diğer diller (Python gibi), yalnızca bazı argümanları iletmek ve argümanları geçirildikleri sıradan bağımsız hale getirmek için bir kişinin adlandırılmış argümanları iletmesine izin verir. Javascript, adlandırılmış argümanların özelliğini doğrudan desteklemez. Onun yerine yaygın olarak kullanılan bir tasarım modeli, özelliklerin / değerlerin bir haritasını geçirmektir. Bu, özelliklere ve değerlere sahip bir nesneyi ileterek yapılabilir veya ES6 ve üzerinde, aslında bir Harita nesnesinin kendisini iletebilirsiniz.

İşte basit bir ES5 örneği:

jQuery's $.ajax() , özelliklere ve değerlere sahip normal bir Javascript nesnesi olan tek bir parametreyi ilettiğiniz bir kullanım biçimini kabul eder. Hangi özellikleri ilettiğiniz, ajax çağrısına hangi argümanların / seçeneklerin aktarılacağını belirler. Bazıları gerekli olabilir, çoğu isteğe bağlıdır. Bir nesnenin özellikleri olduklarından, belirli bir sıra yoktur. Aslında, bu nesneye aktarılabilen 30'dan fazla farklı özellik vardır, yalnızca bir (url) gereklidir.

İşte bir örnek:

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

Uygulamanın içinde, $.ajax()daha sonra gelen nesnede hangi özelliklerin aktarıldığını sorgulayabilir ve bunları adlandırılmış argümanlar olarak kullanabilir. Bu, for (prop in obj)tüm özellikleri bir diziye alarak Object.keys(obj)veya bu diziyi yineleyerek yapılabilir.

Bu teknik, çok sayıda bağımsız değişken olduğunda ve / veya birçok bağımsız değişken isteğe bağlı olduğunda Javascript'te çok yaygın olarak kullanılır. Not: Bu, minimum geçerli argüman kümesinin mevcut olduğundan emin olmak ve arayan kişiye yetersiz argüman iletilirse eksik olan bazı hata ayıklama geri bildirimleri vermek için uygulama işlevine bir yük getirir (muhtemelen yararlı bir hata mesajı ile bir istisna atarak) .

Bir ES6 ortamında, yukarıda aktarılan nesne için varsayılan özellikler / değerler oluşturmak için yok etme kullanmak mümkündür. Bu, bu referans makalesinde daha ayrıntılı olarak tartışılmaktadır .

İşte o makaleden bir örnek:

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

Bu , işleve iletilen bir nesnedeki start, endve stepözellikleri için varsayılan özellikler ve değerler oluşturur selectEntries().

İşlev bağımsız değişkenleri için varsayılan değerler

ES6'da Javascript, bağımsız değişkenler için varsayılan değerler için yerleşik dil desteği ekler.

Örneğin:

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

multiply(5); // 5

Bunun MDN'de kullanılabileceği yollar hakkında daha fazla açıklama burada .


Öyleyse, uyarlanabilir bir işleve bağlı kalmalı ve bunu işlev aşırı yük cephesini uygulamak için en iyi uygulama olarak kabul etmeliyim?
Travis J

2
@TravisJ - evet, uyarlanabilir işlev Javascript'te aşırı yüklemelerin yapılma şeklidir. Diğer seçeneğiniz, farklı argümanlarla ayrı olarak adlandırılmış bir işlev kullanmaktır. İki uygulamanın ortak hiçbir yanı yoksa, o zaman her ikisi de kabul edilebilir bir uygulamadır. İki uygulama aslında aynı şeyi yapıyor, ancak farklı argümanlarla başlıyorsa, arayüzünüzü uyarlanabilir işlevi kullanmak için daha kompakt hale getirdiğini ve iki ilgili uygulama arasında kodu paylaşma fırsatı verdiğini düşünüyorum.
jfriend00

Hem İngilizce hem de gerçek kodda açıklanan bazı kod örnekleri eklendi.
jfriend00

Bunu denediğimde Safari'nin en son sürümünde bir hata, beklenmeyen simge '=' alıyorum resetProgressBar: function(display_errors, lockout = false).
Nick

@Nick - Bu ES6 uyumluluk tablosuna göre , varsayılan parametre değerleri Safari 10 ve sonraki sürümlerde çalışmalıdır. Başına bu MDN sayfasında , Safari'de "hayır desteği" diyor. Bir Mac'im yok, bu yüzden kendim test edemiyorum. Genel olarak, birçok tarayıcıda daha sonra uygulanan ES6 özelliklerinden biri gibi görünüyor. Örneğin, henüz iOS9'da gibi görünmüyor.
jfriend00

33

JavaScript'te bir işlevin aşırı yüklenmesi birçok şekilde yapılabilir. Hepsi, tüm işlemleri gerçekleştiren veya alt işlevlere / süreçlere delege eden tek bir ana işlevi içerir.

En yaygın basit tekniklerden biri basit bir geçişi içerir:

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;
    }
}

Daha zarif bir teknik, bir dizi (veya her bağımsız değişken sayımı için aşırı yükleme yapmıyorsanız nesne ) kullanmak olacaktır:

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

Bu önceki örnek çok zarif değildir, herhangi biri değiştirebilir fooArrve biri 2'den fazla argüman geçirirse başarısız olur foo, bu nedenle daha iyi bir biçim, bir modül kalıbı ve birkaç kontrol kullanmak olacaktır:

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;
}());

Elbette aşırı yüklemeleriniz dinamik sayıda parametre kullanmak isteyebilir, böylece fnskoleksiyon için bir nesne kullanabilirsiniz .

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;
}());

Kişisel tercihim switch, ana işlevi topluyor olsa da, olma eğilimindedir . Bu tekniği nerede kullanacağıma dair yaygın bir örnek bir erişimci / mutatör yöntemi olabilir:

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

Bu, bir alternatifin güzel bir örneğidir :)
Travis J

1
Güzel, 2. tekniği beğendim
Nick Rolando

8

Yöntem aşırı yüklemesini tam anlamıyla yapamazsınız. javaVeya içinde desteklendiği şekilde değil c#.

Sorun, JavaScript'in yöntem aşırı yüklemesini yerel olarak desteklememesidir. Bu nedenle, aynı ada sahip iki veya daha fazla işlevi görür / ayrıştırırsa, yalnızca son tanımlanan işlevi dikkate alır ve öncekilerin üzerine yazar.

Vakaların çoğu için uygun olduğunu düşündüğüm yollardan biri şu:

Bir yönteminiz olduğunu söyleyelim

function foo(x)
{
} 

JavaScript'te mümkün olmayan aşırı yükleme yöntemi yerine yeni bir yöntem tanımlayabilirsiniz.

fooNew(x,y,z)
{
}

1. işlevi aşağıdaki gibi değiştirin -

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

Bu tür aşırı yüklenmiş birçok yönteminiz varsa, switchyalnızca if-elseifadeler yerine kullanmayı düşünün .

( daha fazla ayrıntı ) Not: Yukarıdaki bağlantı, bununla ilgili ek ayrıntılar içeren kişisel bloguma gider.


Bu bir sorun değil, bu bir özellik.
inetphantom

4

Argüman numarasına göre biraz farklı bir aşırı yükleme yaklaşımı kullanıyorum. Ancak John Fawcett'in yaklaşımının da iyi olduğuna inanıyorum. Burada örnek, John Resig'in (jQuery's Author) açıklamalarına dayalı kod.

// 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);
            }
        };
    }

kullanılabilirlik:

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

JavaScript'te işlevi yalnızca bir kez uygulayabilir ve işlevi parametreler olmadan çalıştırabilirsiniz myFunc() Daha sonra seçeneklerin 'tanımsız' olup olmadığını kontrol edin

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

3

Tanımlanan bu soruna zarif bir çözüm geliştirmeye çalıştım Burada . Demoyu burada bulabilirsiniz . Kullanım şu şekildedir:

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);

Bunu başarmak için kullanılan yöntemler:

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
Girdileri idare etmek için çok akıllı bir fonksiyon.
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

JS'de Aşırı Yüklemede Sorun Yok, pb işlevi aşırı yüklerken temiz bir kod nasıl korunur?

İki şeye dayalı olarak temiz bir koda sahip olmak için bir yönlendirme kullanabilirsiniz :

  1. Bağımsız değişken sayısı (işlevi çağırırken).
  2. Bağımsız değişkenlerin türü (işlevi çağırırken)

      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

JavaScript fonksiyon aşırı yükleme seçeneklerine sahip olmadığından bunun yerine nesne kullanılabilir. Bir veya iki gerekli bağımsız değişken varsa, bunları options nesnesinden ayrı tutmak daha iyidir. Burada, options nesnesinde değerin iletilmemesi durumunda options nesnesinin ve doldurulan değerlerin varsayılan değere nasıl kullanılacağına dair bir örnek.

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 + "}";

}

İşte options nesnesinin nasıl kullanılacağına dair bir örnek


2

Bunun için, işlevi bir nesneye ekleyen bir işlev oluşturmanız gerekir, ardından işleve gönderdiğiniz argümanların miktarına bağlı olarak çalıştırılır:

<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

Aynı işlevsellik için bağımsız değişken grupları arasında ayrım yapma yeteneğini elde etmek için bir ana işlev içine alt işlevler eklemeyi seviyorum.

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

Başarmaya çalıştığınız şey en iyi şekilde işlevin yerel argümanlar değişkeni kullanılarak yapılır .

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

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

Bunun nasıl çalıştığına dair daha iyi bir açıklamayı burada bulabilirsiniz .


Peki ya çarpışma tespiti? Bu, parametresiz işlevleri kullanmanın veya var olup olmadığını kontrol etmenin güzel bir yoludur, ancak aşırı yükleme söz konusu olduğunda gerçekten en iyi uygulama değildir.
Travis J
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.