Có thể lấy tất cả các đối số của một hàm dưới dạng một đối tượng bên trong hàm đó không?


Câu trả lời:


346

Sử dụng arguments. Bạn có thể truy cập nó như một mảng. Sử dụng arguments.lengthcho số lượng đối số.


46
Điều này chỉ hoạt động cho JavaScript truyền thống function, không phải =>chức năng mũi tên béo ES2015 + . Đối với những người đó, bạn sẽ muốn sử dụng ...argstrong định nghĩa hàm như vậy : (...args) => console.log(args).
Sawtaytoes

141

Các đối sốmột đối tượng giống như mảng (không phải là một mảng thực tế). Hàm ví dụ ...

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

Hãy dùng thử ...

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]

Chi tiết đầy đủ: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Fiances_and_feft_scope/argument


3
Tại sao không đăng kết quả ở đây quá? :)
Jonathan Azulay

2
Điều này tốt hơn nhiều so với câu trả lời được chấp nhận vì nó chứa một đoạn mã làm việc và hiển thị đầu ra. Câu trả lời được chấp nhận là quá thưa thớt.
Mac

Câu trả lời tốt ... sẽ là một câu trả lời tuyệt vời với việc mở rộng trên "không phải là một mảng thực tế"
terpinmd

Tôi đã thêm một liên kết đến một mô tả đơn giản: "Đối tượng giống như mảng" chỉ là "Đối tượng có thuộc tính độ dài của Số nguyên không âm và thường là một số thuộc tính được lập chỉ mục." Từ liên kết mozilla: "Nó tương tự như một Array, nhưng không có bất kỳ thuộc tính Array nào ngoại trừ chiều dài."
Lu-ca

31

ES6 cho phép một cấu trúc trong đó một đối số chức năng được chỉ định bằng ký hiệu "...", chẳng hạn như

function testArgs (...args) {
 // Where you can test picking the first element
 console.log(args[0]); 
}

3
Đây dường như là cách duy nhất khi sử dụng chức năng mũi tên. a = () => {console.log(arguments);}; a('foo');cho -- Uncaught ReferenceError: arguments is not defined Tuy nhiên a = (...args) => {console.log(args);}; a('foo');cho["foo"]
David Baucum

1
@DavidBaucum đúng rồi. Bởi vì hàm mũi tên không tạo ra một phạm vi mới và "đối số" được thu thập từ phạm vi đó. Nhưng trường hợp xấu nhất không phải là ReferenceError. Đó là "đối số" được thu thập từ một phạm vi bên ngoài. Sau đó, bạn không nhận được ngoại lệ, và có thể các lỗi lạ trong ứng dụng của bạn.
pssandstrom

1
Đây cũng được gọi là "tham số nghỉ ngơi", xem developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ ,.
Dennis

21

Đối argumentstượng là nơi các đối số chức năng được lưu trữ.

Đối tượng đối tượng hoạt động và trông giống như một mảng, về cơ bản là, nó chỉ không có các phương thức mà mảng thực hiện, ví dụ:

Array.forEach(callback[, thisArg]);

Array.map(callback[, thisArg])

Array.filter(callback[, thisArg]);

Array.slice(begin[, end])

Array.indexOf(searchElement[, fromIndex])

Tôi nghĩ rằng cách tốt nhất để chuyển đổi một argumentsđối tượng thành một mảng thực là như vậy:

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

Điều đó sẽ làm cho nó một mảng;

tái sử dụng:

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

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

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

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

kết quả:

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


1
[].slice.apply(arguments);Không thể là cách tốt nhất vì nó gây ra sự phân bổ mảng trống không cần thiết.
Thomas Eding

10

Bạn cũng có thể chuyển đổi nó thành một mảng nếu bạn thích. Nếu thuốc generic Array có sẵn:

var args = Array.slice(arguments)

Nếu không thì:

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

từ Mozilla MDN :

Bạn không nên cắt các đối số vì nó ngăn chặn tối ưu hóa trong các công cụ JavaScript (ví dụ V8).


2
Cảm ơn các cập nhật. Sử dụng JSON.opesify và JSON.parse thay thế: function foo() { foo.bar = JSON.stringify(arguments); foo.baz = JSON.parse(foo.bar); } Nếu cần bảo quản thay vì xâu chuỗi , hãy sử dụng thuật toán nhân bản có cấu trúc bên trong . Nếu các nút DOM được thông qua, hãy sử dụng XMLSerializer như trong một câu hỏi không liên quan . with (new XMLSerializer()) {serializeToString(document.documentElement) }
Paul Sweatte

7

Như nhiều người khác đã chỉ ra, argumentschứa tất cả các đối số được truyền cho một hàm.

Nếu bạn muốn gọi một hàm khác có cùng đối số, hãy sử dụng apply

Thí dụ:

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

debug("message", "another argument")

4

Câu trả lời tương tự với Gunnar, với ví dụ đầy đủ hơn: Bạn thậm chí có thể trả lại toàn bộ nội dung:

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

Đầu ra:

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

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


3

Có nếu bạn không biết có bao nhiêu đối số có thể tại thời điểm khai báo hàm thì bạn có thể khai báo hàm không có tham số và có thể truy cập tất cả các biến bằng mảng đối số được truyền tại thời điểm gọi hàm.


2

Trong ES6, bạn có thể làm một cái gì đó như thế này:

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

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


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


1
Bạn thậm chí có thể thực hiện `` `function foo (a, b, ... c) {console.log (a, b, c); } `` `
TitouanT

-11

Trong ES6, sử dụng 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"

Đối với mã không phải ES6, hãy sử dụng JSON.opesify và 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]

Nếu cần bảo quản thay vì xâu chuỗi , hãy sử dụng thuật toán nhân bản có cấu trúc bên trong .

Nếu các nút DOM được thông qua, hãy sử dụng XMLSerializer như trong một câu hỏi không liên quan .

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

Nếu chạy dưới dạng bookmarklet, bạn có thể cần phải bọc từng đối số dữ liệu có cấu trúc trong hàm tạo Lỗi JSON.stringifyđể hoạt động chính xác.

Người giới thiệu


3
Thứ nhất: điều này sẽ sao chép bất cứ đối tượng nào được truyền vào. Thứ hai: không phải mọi thứ đều có thể được xâu chuỗi thành JSON. Cụ thể: các hàm, các đối tượng DOM, cho biết ngày xâu chuỗi thành chuỗi ...
John Dvorak

@JanDvorak Bạn có thể chỉnh sửa câu trả lời của tôi bằng một hàm xử lý các đối tượng, hàm và ngày DOM không?
Paul Sweatte

1
+1, cố gắng truyền các đối số để báo cáo lỗi dưới dạng chuỗi, đối tượng kết thúc dưới dạng chuỗi '[Đối số đối tượng]' và ghi nhật ký đó vào bảng điều khiển không hiển thị các giá trị. Mặc dù nó dường như không trả lời OP, nhưng nó trả lời câu hỏi của tôi, cảm ơn!
Giăng
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.