Truyền một mảng làm tham số hàm trong JavaScript


290

Tôi muốn gọi một hàm sử dụng một mảng làm tham số:

const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it

function call_me (param0, param1, param2 ) {
  // ...
}

Có cách nào tốt hơn để chuyển nội dung xvào call_me()?

Câu trả lời:


421
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);

Xem tài liệu MDN cho Function.prototype.apply().


Nếu môi trường hỗ trợ ECMAScript 6, bạn có thể sử dụng đối số trải rộng thay thế:

call_me(...args);

9
Như một lưu ý phụ, nếu bất cứ ai muốn vượt qua một mảng kết hợp (khóa được đặt tên) thay vào đó, thì hãy sử dụng một đối tượng. Đến từ PHP (và luôn dẫn đến chủ đề này bởi google) điều này khiến tôi mất một thời gian để tìm ra. Bạn có thể truyền toàn bộ đối tượng như một tham số sau đó. w3schools.com/js/js_objects.asp
timhc22

Cảm ơn đã chỉ ra đối số 'lây lan'! Không biết về nó.
Thomas An

@timhc - bình luận ghi chú bên cạnh của bạn rất hấp dẫn, nhưng tôi không thể phân tích nó (Tôi là một javascript noob làm việc thông qua một vài hướng dẫn). Trong JS, một mảng kết hợp một đối tượng theo một số hướng dẫn.
NateT

@ timhc22 và khi sử dụng đối tượng json để chuyển làm tham số cho hàm, đừng quên Hủy tham số để dễ đọc hơn
Muhammad Omer Aslam

113

Tại sao bạn không vượt qua toàn bộ mảng và xử lý nó khi cần bên trong hàm?

var x = [ 'p0', 'p1', 'p2' ]; 
call_me(x);

function call_me(params) {
  for (i=0; i<params.length; i++) {
    alert(params[i])
  }
}

37
Đó là vì tôi không thể sửa đổi call_me (). Nó được định nghĩa trong một số thư viện khác và không thể gây rối với API.
Robert

62
+1 vì mặc dù nó không trả lời câu hỏi ban đầu, nhưng có lẽ 100 nghìn người đã xem trang này đang tìm kiếm.
Ishikawa

Ai đó có thể giải thích dòng "call_me (x)" đang làm gì không? Có vẻ như nó là một tên chức năng mà không có từ khóa chức năng? Chính xác thì nó đang làm gì?
bơi

1
@swam Đó là một cuộc gọi đến call_mechức năng. Nó chỉ thiếu một dấu chấm phẩy ở cuối.
SantiBailors

@swam nó đang thực thi hàm call_me (params) được khai báo.
Julio Rodriguez

43

Giả sử rằng call_me là một hàm toàn cục, vì vậy bạn không mong đợi nó được đặt.

var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);

41

Trong tiêu chuẩn ES6 có một toán tử trải rộng mới ...thực hiện chính xác điều đó.

call_me(...x)

Nó được hỗ trợ bởi tất cả các trình duyệt chính trừ IE.

Toán tử lây lan có thể thực hiện nhiều điều hữu ích khác và tài liệu được liên kết thực hiện công việc thực sự tốt trong việc thể hiện điều đó.



7

Như @KaptajnKold đã trả lời

var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);

Và bạn cũng không cần xác định mọi tham số cho hàm call_me. Bạn chỉ có thể sử dụngarguments

function call_me () {
    // arguments is a array consisting of params.
    // arguments[0] == 'p0',
    // arguments[1] == 'p1',
    // arguments[2] == 'p2'
}

4
Đây là một thực tế tồi tệ như vậy ... bạn sẽ không thể thấy hàm cần gì và mọi tham số là tùy chọn nếu bạn nhìn vào hàm.
Robin

3

Lưu ý điều này

function FollowMouse() {
    for(var i=0; i< arguments.length; i++) {
        arguments[i].style.top = event.clientY+"px";
        arguments[i].style.left = event.clientX+"px";
    }

};

// ---------------------------

trang html

<body onmousemove="FollowMouse(d1,d2,d3)">

<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>


</body>

có thể gọi hàm với bất kỳ đối số

<body onmousemove="FollowMouse(d1,d2)">

hoặc là

<body onmousemove="FollowMouse(d1)">

Đây rõ ràng là một phần của câu trả lời. "đối số" chắc chắn là cần thiết để lấy lại mảng sau cuộc gọi. Cảm ơn!
FlorianB

2

Các đối số chức năng cũng có thể là Mảng:

function foo([a,b,c], d){
  console.log(a,b,c,d);
}

foo([1,2,3], 4)

Tất nhiên người ta cũng có thể sử dụng lây lan :

function foo(a, b, c, d){
  console.log(a, b, c, d);
}

foo(...[1, 2, 3], 4)


2

Trong khi sử dụng toán tử trải, chúng ta phải lưu ý rằng nó phải là tham số cuối cùng hoặc duy nhất được truyền. Khác nó sẽ thất bại.

function callMe(...arr){ //valid arguments
    alert(arr);
}

function callMe(name, ...arr){ //valid arguments
    alert(arr);
}

function callMe(...arr, name){ //invalid arguments
    alert(arr);
}

Nếu bạn cần truyền một mảng làm đối số bắt đầu, bạn có thể làm:

function callMe(arr, name){
    let newArr = [...arr];
    alert(newArr);
}

1

bạn có thể sử dụng toán tử trải rộng ở dạng cơ bản hơn

[].concat(...array)

trong trường hợp các hàm trả về mảng nhưng được dự kiến ​​sẽ chuyển qua làm đối số

Thí dụ:

function expectArguments(...args){
  return [].concat(...args);
}

JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))

0

Câu trả lời đã được đưa ra, nhưng tôi chỉ muốn đưa miếng bánh của mình. Những gì bạn muốn đạt được được gọi method borrowingtrong ngữ cảnh của JS, rằng khi chúng ta lấy một phương thức từ một đối tượng và gọi nó trong ngữ cảnh của một đối tượng khác. Nó là khá phổ biến để thực hiện các phương thức mảng và áp dụng chúng cho các đối số. Tôi sẽ cho bạn một ví dụ.

Vì vậy, chúng ta có hàm băm "siêu", lấy hai số làm đối số và trả về chuỗi băm "siêu an toàn":

function hash() {
  return arguments[0]+','+arguments[1];
}

hash(1,2); // "1,2" whoaa

Cho đến nay rất tốt, nhưng chúng tôi có ít vấn đề với cách tiếp cận ở trên, nó bị hạn chế, chỉ hoạt động với hai số, không động, hãy làm cho nó hoạt động với bất kỳ số nào và cộng với bạn không phải vượt qua một mảng (bạn có thể nếu bạn vẫn khăng khăng). Ok, nói đủ rồi, chúng ta hãy chiến đấu!

Giải pháp tự nhiên là sử dụng arr.joinphương pháp:

function hash() {
  return arguments.join();
}

hash(1,2,4,..); //  Error: arguments.join is not a function

Trời ơi. Thật không may, điều đó sẽ không làm việc. Bởi vì chúng ta đang gọi hàm băm (đối số) và đối tượng là cả hai lần lặp và giống như mảng, nhưng không phải là một mảng thực sự. Làm thế nào về cách tiếp cận dưới đây?

function hash() {
  return [].join.call(arguments);
}

hash(1,2,3,4); // "1,2,3,4" whoaa

Thủ thuật được gọi là method borrowing.

Chúng tôi mượn một joinphương thức từ một mảng thông thường [].join.Và sử dụng [].join.callđể chạy nó trong ngữ cảnh arguments.

Tại sao nó hoạt động?

Đó là bởi vì thuật toán bên trong của phương thức gốc arr.join(glue)rất đơn giản.

Lấy từ đặc điểm kỹ thuật gần như là as-is:

Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
Do so until this.length items are glued.
Return result.

Vì vậy, về mặt kỹ thuật, nó cần cái này và tham gia cái này [0], cái này [1]. Nó cố ý được viết theo cách cho phép bất kỳ mảng nào - như thế này (không phải là trùng hợp ngẫu nhiên, nhiều phương pháp tuân theo thực tiễn này). Đó là lý do tại sao nó cũng hoạt động vớithis=arguments.

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.