Truyền đối số chuyển tiếp sang chức năng javascript khác


386

Tôi đã thử những điều sau đây nhưng không thành công:

function a(args){
    b(arguments);
}

function b(args){
    // arguments are lost?
}

a(1,2,3);

Trong hàm a, tôi có thể sử dụng từ khóa đối số để truy cập vào một mảng các đối số, trong hàm b chúng bị mất. Có cách nào để truyền đối số cho một hàm javascript khác như tôi cố gắng không?


3
@ BobStein-VisiBone Đồng ý. Thêm vào đó, lưu ý rằng đó argumentskhông thực sự là một mảng (mà là một đối tượng thực hiện ngữ nghĩa giống như mảng ) và do đó, nó không hoàn toàn rõ ràng ngay từ cái nhìn đầu tiên liệu nó có thể được sử dụng theo cách tương tự như một mảng thực tế hay không.
Jules

@Jules vẫn bỏ phiếu để mở lại sau tất cả những năm này. Huy hiệu để đốt cháy công việc có giá trị của người khác là gì? Rất nhiều trong số đó để đi xung quanh.
Bob Stein

Câu trả lời:


542

Sử dụng .apply()để có cùng quyền truy cập argumentsvào chức năng b, như thế này:

function a(){
    b.apply(null, arguments);
}
function b(){
   alert(arguments); //arguments[0] = 1, etc
}
a(1,2,3);​

Bạn có thể kiểm tra nó ở đây .


21
@Brett - Bạn có thể sao chép nó vào một mảng sau đó thao tác điều đó trước khi chuyển nó đi, ví dụ:var copy = [].slice.call(arguments); <remove what you want> myFunc.apply(this, copy);
Nick Craver

18
nhưng sử dụng applynhư thế này có thể làm hỏng phạm vi của b(ví dụ: nếu đó là một chức năng bên trong của một đối tượng)
vsync

3
@vsync điểm tốt, nhưng vấn đề rất dễ giải quyết: truyền đối tượng làm đối số đầu tiên để áp dụng.
Tad Lispy

11
không có nghĩa gì khi sử dụng "args" và "argument" cùng nhau ...
anh chàng

3
Nhưng sau đó "cái này" có thể được thay đổi thành cái gì đó khác với bản gốc của b này.
trusktr

223

Toán tử trải

Toán tử trải rộng cho phép một biểu thức được mở rộng ở những nơi có nhiều đối số (đối với các lệnh gọi hàm) hoặc nhiều phần tử (đối với các mảng bằng chữ) được mong đợi.

ECMAScript ES6 đã thêm một toán tử mới cho phép bạn thực hiện điều này theo cách thực tế hơn: ... Toán tử trải rộng .

Ví dụ mà không sử dụng applyphương thức:

function a(...args){
  b(...args);
  b(6, ...args, 8) // You can even add more elements
}
function b(){
  console.log(arguments)
}

a(1, 2, 3)

Note Đoạn mã này trả về lỗi cú pháp nếu trình duyệt của bạn vẫn sử dụng ES5.

Lưu ý của biên tập viên: Vì đoạn mã sử dụng console.log(), bạn phải mở bảng điều khiển JS của trình duyệt để xem kết quả - sẽ không có kết quả trong trang.

Nó sẽ hiển thị kết quả này:

Hình ảnh ví dụ về toán tử lây lan

Nói tóm lại, toán tử trải rộng có thể được sử dụng cho các mục đích khác nhau nếu bạn đang sử dụng mảng, do đó, nó cũng có thể được sử dụng cho các đối số hàm, bạn có thể thấy một ví dụ tương tự được giải thích trong các tài liệu chính thức: Tham số phần còn lại


6
Đây là một nhà điều hành rất tốt và tôi thực sự mong muốn sử dụng nó. Tuy nhiên, nó sẽ không xảy ra. Trình duyệt duy nhất đã hỗ trợ toán tử trải rộng là FF tại thời điểm này. Xem bảng tương thích để biết dữ liệu cập nhật, đầy đủ: kangax.github.io/compat-table/es6/#s lây_%28...%29_operator
TMG

10
Tại sao nó không nên được sử dụng? Tương đối dễ dàng để dịch mã với babel, bạn có tất cả các tính năng mới và khả năng tương thích nhiều hơn với các trình duyệt cũ hơn.
adgelbfish

Điều này tốt hơn giải pháp đầu tiên vì nó hoạt động trong chức năng được xác định bằng toán tử mũi tên.
sarfata

Bạn không cần ...argstrong achức năng. Bạn chỉ có thể thực hiện một chức năng không có đối số và vượt qua chúng vào bvới...arguments
cronoklee

1
Đối với bất kỳ ai đọc câu trả lời này: Trái ngược với nhận xét của @ cronoklee, việc chỉ định rõ ràng ...argsađầu vào của có thể quan trọng nếu bạn có các hàm lồng nhau.
Arshia001

81

Lời giải thích rằng không có nguồn cung cấp câu trả lời khác là những lập luận ban đầu vẫn có sẵn, nhưng không phải ở vị trí ban đầu trong các argumentsđối tượng.

Đối argumentstượng chứa một phần tử cho mỗi tham số thực tế được cung cấp cho hàm. Khi bạn gọi abạn cung cấp ba đối số: số 1, 2và, 3. Vì vậy, argumentscó chứa [1, 2, 3].

function a(args){
    console.log(arguments) // [1, 2, 3]
    b(arguments);
}

Khi bạn gọi b, tuy nhiên, bạn vượt qua chính xác một lập luận: a's argumentsđối tượng. Vì vậy, argumentscó chứa [[1, 2, 3]](tức là một yếu tố, đó là a's argumentsđối tượng, trong đó có các thuộc tính có chứa các đối số gốc để a).

function b(args){
    // arguments are lost?
    console.log(arguments) // [[1, 2, 3]]
}

a(1,2,3);

Như @Nick đã trình bày, bạn có thể sử dụng applyđể cung cấp một argumentsđối tượng được đặt trong cuộc gọi.

Sau đây đạt được kết quả tương tự:

function a(args){
    b(arguments[0], arguments[1], arguments[2]); // three arguments
}

Nhưng applylà giải pháp chính xác trong trường hợp chung.


Bạn nên luôn luôn vượt qua thisđể apply?
Flimm

1
@ Flimm, vâng, vì các đối số là đối số thứ hai, nên phải có một cái gì đó cho đối số thứ nhất (nó có thể là null ).
RobG

0

thử cái này

function global_func(...args){
  for(let i of args){
    console.log(i)
  }
}


global_func('task_name', 'action', [{x: 'x'},{x: 'x'}], {x: 'x'}, ['x1','x2'], 1, null, undefined, false, true)




//task_name
//action
//(2) [{...},
//    {...}]
//    {
//        x:"x"
//    }
//(2) [
//        "x1",
//        "x2"
//    ]
//1
//null
//undefined
//false
//true
//func
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.