Apakah mungkin untuk mendapatkan semua argumen fungsi sebagai objek tunggal di dalam fungsi itu?

Jawaban:

346

Gunakan arguments. Anda dapat mengaksesnya seperti sebuah array. Gunakan arguments.lengthuntuk jumlah argumen.

Thomas Eding
sumber
46
Ini hanya berfungsi untuk JavaScript tradisional function, bukan =>fungsi panah gemuk ES2015 + . Bagi mereka, Anda akan ingin menggunakan ...argsdalam definisi fungsi seperti: (...args) => console.log(args).
Sawtaytoes
141

The argumen adalah sebuah objek array-seperti (bukan array yang sebenarnya). Fungsi contoh ...

function testArguments () // <-- notice no arguments specified
{
    console.log(arguments); // outputs the arguments to the console
    var htmlOutput = "";
    for (var i=0; i < arguments.length; i++) {
        htmlOutput += '<li>' + arguments[i] + '</li>';
    }
    document.write('<ul>' + htmlOutput + '</ul>');
}

Cobalah ...

testArguments("This", "is", "a", "test");  // outputs ["This","is","a","test"]
testArguments(1,2,3,4,5,6,7,8,9);          // outputs [1,2,3,4,5,6,7,8,9]

Detail lengkap: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments

Luke
sumber
3
Mengapa tidak memposting hasilnya di sini juga? :)
Jonathan Azulay
2
Ini jauh lebih baik daripada jawaban yang diterima karena berisi potongan kode yang berfungsi dan menampilkan output. Jawaban yang diterima terlalu jarang.
Mac
Jawaban yang bagus ... akan menjadi jawaban yang bagus dengan memperluas pada "bukan array yang sebenarnya"
terpinmd
Saya menambahkan tautan ke deskripsi sederhana: "Objek Array-like" hanyalah "Obyek yang memiliki properti panjang dari Integer non-negatif, dan biasanya beberapa properti yang diindeks." Dari tautan mozilla: "Ini mirip dengan Array, tetapi tidak memiliki properti Array apa pun kecuali panjang."
Luke
31

ES6 memungkinkan konstruk di mana argumen fungsi ditentukan dengan notasi "..." seperti

function testArgs (...args) {
 // Where you can test picking the first element
 console.log(args[0]); 
}
Gunnar Forsgren - Mobimation
sumber
3
Ini tampaknya menjadi satu-satunya cara ketika menggunakan fungsi panah. a = () => {console.log(arguments);}; a('foo');memberikan -- Uncaught ReferenceError: arguments is not defined Namun a = (...args) => {console.log(args);}; a('foo');memberi["foo"]
David Baucum
1
@ DavidBaucum itu benar. Karena fungsi panah tidak membuat ruang lingkup baru, dan "argumen" dikumpulkan dari ruang lingkup. Tetapi skenario terburuk bukanlah ReferenceError. Itu adalah bahwa "argumen" dikumpulkan dari ruang lingkup luar. Maka Anda tidak terkecuali, dan mungkin ada bug aneh di aplikasi Anda.
pgsandstrom
1
Ini juga disebut "parameter rest", lihat developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… .
Dennis
21

The argumentsobjek adalah di mana argumen fungsi disimpan.

Objek argumen bertindak dan terlihat seperti array, pada dasarnya adalah, hanya saja tidak memiliki metode yang dilakukan array, misalnya:

Array.forEach(callback[, thisArg]);

Array.map(callback[, thisArg])

Array.filter(callback[, thisArg]);

Array.slice(begin[, end])

Array.indexOf(searchElement[, fromIndex])

Saya pikir cara terbaik untuk mengubah argumentsobjek menjadi Array nyata adalah seperti ini:

argumentsArray = [].slice.apply(arguments);

Itu akan membuatnya menjadi array;

dapat digunakan kembali:

function ArgumentsToArray(args) {
    return [].slice.apply(args);
}

(function() {
   args = ArgumentsToArray(arguments);

   args.forEach(function(value) {
      console.log('value ===', value);
   });

})('name', 1, {}, 'two', 3)

hasil:

> value === name
> value === 1
> value === Object {}
> value === two
>value === 3

iConnor
sumber
1
[].slice.apply(arguments);tidak bisa menjadi cara terbaik karena menyebabkan alokasi array kosong yang tidak perlu.
Thomas Eding
10

Anda juga dapat mengonversinya menjadi sebuah array jika Anda mau. Jika Array generics tersedia:

var args = Array.slice(arguments)

Jika tidak:

var args = Array.prototype.slice.call(arguments);

dari Mozilla MDN :

Anda tidak boleh mengiris argumen karena itu mencegah optimisasi dalam mesin JavaScript (V8 misalnya).

Iman Mohamadi
sumber
2
Terima kasih atas pembaruannya. Gunakan JSON.stringify dan JSON.parse sebagai alternatif: function foo() { foo.bar = JSON.stringify(arguments); foo.baz = JSON.parse(foo.bar); } Jika pelestarian diperlukan alih-alih pengencangan, gunakan algoritma kloning terstruktur internal . Jika node DOM dilewatkan, gunakan XMLSerializer seperti dalam pertanyaan yang tidak terkait . with (new XMLSerializer()) {serializeToString(document.documentElement) }
Paul Sweatte
7

Seperti yang banyak ditunjukkan, argumentsberisi semua argumen yang diteruskan ke fungsi.

Jika Anda ingin memanggil fungsi lain dengan argumen yang sama, gunakan apply

Contoh:

var is_debug = true;
var debug = function() {
  if (is_debug) {
    console.log.apply(console, arguments);
  }
}

debug("message", "another argument")
Lasse Skindstad Ebert
sumber
4

Jawaban yang mirip dengan Gunnar, dengan contoh yang lebih lengkap: Anda bahkan dapat mengembalikan semuanya secara transparan:

function dumpArguments(...args) {
  for (var i = 0; i < args.length; i++)
    console.log(args[i]);
  return args;
}

dumpArguments("foo", "bar", true, 42, ["yes", "no"], { 'banana': true });

Keluaran:

foo
bar
true
42
["yes","no"]
{"banana":true}

https://codepen.io/fnocke/pen/mmoxOr?editors=0010

Frank Nocke
sumber
3

Ya jika Anda tidak tahu bahwa berapa banyak argumen yang mungkin pada saat deklarasi fungsi maka Anda dapat mendeklarasikan fungsi tersebut tanpa parameter dan dapat mengakses semua variabel dengan array argumen yang diteruskan pada saat pemanggilan fungsi.

Rubi saini
sumber
2

Di ES6 Anda dapat melakukan sesuatu seperti ini:

function foo(...args) 
{
   let [a,b,...c] = args;

   console.log(a,b,c);
}


foo(1, null,"x",true, undefined);

Kamil Kiełczewski
sumber
1
Anda bahkan dapat melakukan fungsi `` `foo (a, b, ... c) {console.log (a, b, c); } `` `
TitouanT
-11

Dalam ES6, gunakan Array.from:

function foo()
  {
  foo.bar = Array.from(arguments);
  foo.baz = foo.bar.join();
  }

foo(1,2,3,4,5,6,7);
foo.bar // Array [1, 2, 3, 4, 5, 6, 7]
foo.baz // "1,2,3,4,5,6,7"

Untuk kode non-ES6, gunakan JSON.stringify dan JSON.parse:

function foo()
  {
  foo.bar = JSON.stringify(arguments); 
  foo.baz = JSON.parse(foo.bar); 
  }

/* Atomic Data */
foo(1,2,3,4,5,6,7);
foo.bar // "{"0":1,"1":2,"2":3,"3":4,"4":5,"5":6,"6":7}"
foo.baz // [object Object]

/* Structured Data */
foo({1:2},[3,4],/5,6/,Date())
foo.bar //"{"0":{"1":2},"1":[3,4],"2":{},"3":"Tue Dec 17 2013 16:25:44 GMT-0800 (Pacific Standard Time)"}"
foo.baz // [object Object]

Jika pelestarian diperlukan alih-alih pengencangan, gunakan algoritma kloning terstruktur internal .

Jika node DOM dilewatkan, gunakan XMLSerializer seperti dalam pertanyaan yang tidak terkait .

with (new XMLSerializer()) {serializeToString(document.documentElement) }

Jika berjalan sebagai bookmarklet, Anda mungkin perlu membungkus masing-masing argumen data terstruktur dalam konstruktor Kesalahan JSON.stringifyagar berfungsi dengan benar.

Referensi

Paul Sweatte
sumber
3
Pertama: ini akan mengkloning objek apa pun yang dilewatkan. Kedua: tidak semuanya dapat dirender ke JSON. Yaitu: fungsi, objek DOM, kata tanggal dirangkai sebagai string ...
John Dvorak
@ JanDvorak Bisakah Anda mengedit jawaban saya dengan fungsi yang menangani objek, fungsi, dan tanggal DOM?
Paul Sweatte
1
+1, mencoba meneruskan argumen untuk pelaporan kesalahan sebagai string, objek berakhir sebagai string '[argumen objek]' dan masuk ke konsol tidak menampilkan nilai. Meskipun sepertinya tidak menjawab OP, ia menjawab pertanyaan saya, terima kasih!
John