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)
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)
Yanıtlar:
Tabii, sadece arguments
nesneyi kullan.
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
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/…
length
özelliği olan herhangi bir nesne üzerinde çalışacak şekilde tanımlanmıştır . Bu arguments
nesneyi içerir . Bunu bilerek ve yöntem concat
döndürür bir kopyasını o üzerinde deniyor 'dizisinin', kolaylıkla dönüştürebilirsiniz arguments
böyle bir gerçek dizi nesne: var args = [].concat.call(arguments)
. Bazı insanlar Array.prototype.concat.call
bunun yerine kullanmayı tercih ederler , ama hoşuma []
gidiyorlar, kısa ve tatlılar!
[...arguments].join()
(Ç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
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).
context
argümanı kodla oluşturabilir ve kullanılmadan önce iletebilirsiniz.
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.
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
- 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.
- 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.
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 arguments
bir 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);
}
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.
(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.
@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];
}
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});
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!
function sumOfAll (var_args) {
return arguments.reduce(function(a, b) {
return a + b;
}, 0);
}
sumOfAll(1,2,3); // returns 6
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
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
arguments
Geçirilen tüm bağımsız değişkenlere erişmek için işlevin içindeyken nesneyi kullanın .
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.