JavaScript değişkeni işlevi için bağımsız değişken sayısı


531

JavaScript'te bir işlev için "sınırsız" değişkenlere izin vermenin bir yolu var mı?

Misal:

load(var1, var2, var3, var4, var5, etc...)
load(var1)



1
@ Hayır, değil. Bu soru, bir dizideki bağımsız değişkenlerle isteğe bağlı sayıda bağımsız değişken içeren bir işlevin nasıl çağrılacağını sorar. Bu böyle bir çağrının nasıl yapılacağını sorar.
Pis

1
Daha kolay arama için böyle bir işleve 'varyasyon işlevi' denir.
gschenk

Yanıtlar:


814

Tabii, sadece argumentsnesneyi kullan.

function foo() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}

1
Tnx. Bir Web görünümünde dizeleri android yerel koddan javascript'e ayrıştırmak için mükemmeldir.
Johan Hoeksma

4
Bu çözüm benim için en iyi sonucu verdi. Teşekkürler. HERE arguments anahtar sözcüğü hakkında daha fazla bilgi .
Kullanıcı2

26
argumentsözel bir "Dizi benzeri" nesnedir, yani uzunluğu vardır, ancak başka dizi işlevi yoktur. Daha fazla bilgi için developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Luke

4
İlginçtir, Javascript'teki Array yöntemleri, lengthözelliği olan herhangi bir nesne üzerinde çalışacak şekilde tanımlanmıştır . Bu argumentsnesneyi içerir . Bunu bilerek ve yöntem concatdöndürür bir kopyasını o üzerinde deniyor 'dizisinin', kolaylıkla dönüştürebilirsiniz argumentsböyle bir gerçek dizi nesne: var args = [].concat.call(arguments). Bazı insanlar Array.prototype.concat.callbunun yerine kullanmayı tercih ederler , ama hoşuma []gidiyorlar, kısa ve tatlılar!
Stijn de Witt

2
@YasirJan kullanımı[...arguments].join()
Willian D. Andrade

179

(Çoğu) son tarayıcılarda, bu sözdizimiyle değişken sayıda bağımsız değişkeni kabul edebilirsiniz:

function my_log(...args) {
     // args is an Array
     console.log(args);
     // You can pass this array as parameters to another function
     console.log(...args);
}

İşte küçük bir örnek:

function foo(x, ...args) {
  console.log(x, args, ...args, arguments);
}

foo('a', 'b', 'c', z='d')

=>

a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
    0: "a"
    1: "b"
    2: "c"
    3: "d"
    length: 4

Belgeler ve diğer örnekler burada: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters


27
Bilginize "geri kalan parametre sözdizimi" denir: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
tanguy_k

4
+1 Bu zarif ve temiz bir çözümdür. Uzun parametre listesinden başka bir fonksiyon çağrısına geçmek için özellikle uygundur ve bu değişken parametrelerin keyfi konumda olması mümkündür.
haxpor


2
İşte tarayıcı desteğini gösteren bir tablo - caniuse.com/#feat=rest-parameters
Brian Burns

1
Ne güzel bir cevap!
Ashish

113

Başka bir seçenek de argümanlarınızı bir bağlam nesnesine iletmektir.

function load(context)
{
    // do whatever with context.name, context.address, etc
}

ve böyle kullan

load({name:'Ken',address:'secret',unused:true})

Bunun avantajı, istediğiniz sayıda adlandırılmış argüman ekleyebilmenizdir ve işlev, uygun gördüğü gibi bunları kullanabilir (veya kullanamaz).


4
Bu daha iyi olur çünkü argüman sırasına olan bağlantıyı kaldırır. Gevşek bağlı arayüzler iyi bir standart uygulamadır ...
Jonas Schubert Erlandsson

9
Tabii, bu bazı durumlarda daha iyi. Ancak diyelim ki bağımsız değişkenler birbirleriyle gerçekten ilgili değildir veya hepsinin eşit anlamı olması gerekir (dizi öğeleri gibi). O zaman OP'nin yolu en iyisidir.
rvighne

1
Bu da güzel, çünkü isterseniz, contextargümanı kodla oluşturabilir ve kullanılmadan önce iletebilirsiniz.
Nate CK

46

Ken'in cevabını en dinamik olarak kabul ediyorum ve bunu bir adım daha ileriye götürmeyi seviyorum. Farklı argümanlarla birden çok kez çağırdığınız bir işlevse - Ken'in tasarımını kullanıyorum, ancak varsayılan değerleri ekliyorum:

function load(context) {

    var defaults = {
        parameter1: defaultValue1,
        parameter2: defaultValue2,
        ...
    };

    var context = extend(defaults, context);

    // do stuff
}

Bu şekilde, çok sayıda parametreniz varsa, ancak her işlev çağrısıyla bunları ayarlamanız gerekmiyorsa, varsayılan olmayanları belirtebilirsiniz. Genişletme yöntemi için jQuery'nin length yöntemini ( $.extend()) kullanabilir, kendi yönteminizi oluşturabilir veya aşağıdakileri kullanabilirsiniz:

function extend() {
    for (var i = 1; i < arguments.length; i++)
        for (var key in arguments[i])
            if (arguments[i].hasOwnProperty(key))
                arguments[0][key] = arguments[i][key];
    return arguments[0];
}

Bu, bağlam nesnesini varsayılanlarla birleştirir ve nesnenizdeki tanımlanmamış değerleri varsayılanlarla doldurur.


3
+1. İyi numara. Varsayılan veya başka bir parametrenin tanımlanması için birçok kazan plakasını kaydeder.
Neil

1
Alt çizgi _.defaults() yöntemi, belirtilen ve varsayılan bağımsız değişkenleri birleştirmek için çok güzel bir alternatiftir.
mbeasley

18

Evet, aynen şöyle:

function load()
{
  var var0 = arguments[0];
  var var1 = arguments[1];
}

load(1,2);

18

Ramast'ın işaret ettiği gibi dinlenme parametresi sözdiziminin kullanılması tercih edilir.

function (a, b, ...args) {}

Ben sadece ... argümanlar argüman bazı güzel özelliği eklemek istiyorum

  1. Bağımsız değişkenler gibi bir nesne değil, bir dizidir. Bu, harita veya sıralama gibi işlevleri doğrudan uygulamanızı sağlar.
  2. Tüm parametreleri içermez, sadece ondan geçirilen parametreleri içerir. Örneğin işlev (a, b, ... args) bu durumda args arguments.length için 3 bağımsız değişkenini içerir.

15

Daha önce de belirtildiği gibi, arguments nesneyi değişken sayıda işlev parametresi almak için .

Aynı bağımsız değişkenlere sahip başka bir işlevi çağırmak istiyorsanız, tuşunu kullanın apply. Hatta argumentsbir diziye dönüştürerek bağımsız değişkenler ekleyebilir veya kaldırabilirsiniz . Örneğin, bu işlev konsola giriş yapmadan önce bazı metinler ekler:

log() {
    let args = Array.prototype.slice.call(arguments);
    args = ['MyObjectName', this.id_].concat(args);
    console.log.apply(console, args);
}

argümanları diziye dönüştürmek için güzel bir çözüm. Bugün bana yardımcı oldu.
Dmytro Medvid

8

Genelde adlandırılmış argümanlar yaklaşımının kullanışlı ve esnek olduğunu kabul etsem de (siparişi önemsemediğiniz sürece, bu durumda argümanlar en kolay olanıdır), mbeasley yaklaşımının maliyeti hakkında endişelerim var (varsayılanları ve uzantıları kullanarak). Bu, varsayılan değerleri çekmek için aşırı bir maliyettir. İlk olarak, varsayılanlar işlevin içinde tanımlanır, böylece her çağrıda yeniden doldurulurlar. İkinci olarak, adlandırılmış değerleri kolayca okuyabilir ve || ile varsayılanları aynı anda ayarlayabilirsiniz. Bu bilgiyi almak için yeni bir nesne oluşturmaya ve birleştirmeye gerek yoktur.

function load(context) {
   var parameter1 = context.parameter1 || defaultValue1,
       parameter2 = context.parameter2 || defaultValue2;

   // do stuff
}

Bu yaklaşık olarak aynı miktarda koddur (belki biraz daha fazla), ancak çalışma zamanı maliyetinin bir kısmı olmalıdır.


Kabul edildi, ancak zarar değerin türüne veya varsayılanın kendisine bağlı. Aksi takdirde (parameter1=context.parameter1)===undefined && (parameter1=defaultValue1)veya daha az kod hacmi için aşağıdaki gibi küçük bir yardımcı işlev görür:function def(providedValue, default) {return providedValue !== undefined ? providedValue : defaultValue;} var parameter1 = def(context.parameter1, defaultValue1) alternatif desenler sağlayın. Bununla birlikte, benim açımım hala duruyor: her işlev çağırma için ekstra nesneler oluşturmak ve birkaç varsayılan değer ayarlamak için pahalı döngüler çalıştırmak çılgın bir yüktür.
mcurland

7

@Roufamatic, arguments anahtar sözcüğünü kullandığını gösterirken ve @Ken, kullanım için bir nesneye harika bir örnek gösterdiğinde, bu örnekte olup bitenlere gerçekten değinmediğimi hissediyorum ve gelecekteki okuyucuları şaşırtabilir veya bir işlevi açıkça belirtmediği için kötü bir uygulama aşılayabilirim / yönteminin değişken miktarda argüman / parametre alması amaçlanmıştır.

function varyArg () {
    return arguments[0] + arguments[1];
}

Başka bir geliştirici kodunuzu ararken bu fonksiyonun parametre almadığını varsaymak çok kolaydır. Özellikle bu geliştirici argümanlara özel değilse anahtar kelimesine . Bu nedenle bir stil kılavuzunu takip etmek ve tutarlı olmak iyi bir fikirdir. Tüm örnekler için Google’ı kullanacağım.

Aynı işlevin değişken parametrelere sahip olduğunu açıkça belirtelim:

function varyArg (var_args) {
    return arguments[0] + arguments[1];
}

Nesne parametresi VS var_args

Bir veri haritasının tek onaylı ve en iyi uygulama yöntemi olduğu için bir nesneye ihtiyaç duyulduğu zamanlar olabilir. İlişkilendirilebilir diziler kaşlarını çatmış ve cesaretini kırmıştır.

SIDENOTE: arguments anahtar sözcüğü, anahtar olarak sayıları kullanan bir nesneyi geri döndürür. Prototip palet miras nesne nesnesidir. JS'de doğru dizi kullanımı için yanıtın sonuna bakın

Bu durumda bunu açıkça ifade edebiliriz. Not: Bu adlandırma kuralı Google tarafından sağlanmamıştır, ancak bir param türünün açık bir beyanına örnektir. Kodunuzda daha katı bir desen oluşturmak istiyorsanız bu önemlidir.

function varyArg (args_obj) {
    return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});

Hangisini seçmeli?

Bu, işlevinizin ve programınızın gereksinimlerine bağlıdır. Örneğin, yalnızca tüm argümanlar boyunca yinelemeli bir süreç üzerinde bir değer tabanı döndürmek istiyorsanız, kesinlikle arguments anahtar sözcüğüne bağlı kalın. Argümanlarınızın tanımına ve verilerin eşlenmesine ihtiyacınız varsa, nesne yöntemi gitmenin yoludur. İki örneğe bakalım ve işimiz bitti!

Bağımsız değişkenlerin kullanımı

function sumOfAll (var_args) {
    return arguments.reduce(function(a, b) {
        return a + b;
    }, 0);
}
sumOfAll(1,2,3); // returns 6

Nesne kullanımı

function myObjArgs(args_obj) {
    // MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
    if (typeof args_obj !== "object") {
        return "Arguments passed must be in object form!";
    }

    return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old

Nesne yerine bir diziye erişme ("... args" rest parametresi)

Cevabın üst kısmında belirtildiği gibi arguments anahtar sözcüğü aslında bir nesne döndürür. Bu nedenle, bir dizi için kullanmak istediğiniz herhangi bir yöntemin çağrılması gerekir. Buna bir örnek:

Array.prototype.map.call(arguments, function (val, idx, arr) {});

Bunu önlemek için rest parametresini kullanın:

function varyArgArr (...var_args) {
    return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5

5

argumentsGeçirilen tüm bağımsız değişkenlere erişmek için işlevin içindeyken nesneyi kullanın .


3

Ken'in önerdiği özelliklere sahip bir Nesnenin iletilmesinin, her nesneye geçici nesneyi tahsis etme ve serbest bırakma maliyetini eklediğini unutmayın. Normal argümanları değere veya referansa göre iletmek genellikle en verimli yöntem olacaktır. Birçok uygulama için performans kritik olmasa da bazıları için olabilir.

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.