Truyền một hàm với tham số là tham số?


151

Có thể truyền một hàm javascript với các tham số là tham số không?

Thí dụ:

$(edit_link).click( changeViewMode( myvar ) );

5
Nó trông giống như JQuery, và rất có thể là vậy, nhưng điều đó không liên quan. Việc sử dụng hoặc tham số và chức năng là như nhau bất kể bạn sử dụng thư viện Javascript nào.
Guffa

@Guffa - Tôi đã tự hỏi liệu nó có nên được gắn thẻ với jQuery không
Russ Cam

1
@Lucia Hãy xem xét thay đổi câu trả lời được chấp nhận cho điều này .
Michał Perłakowski

Nếu bạn đang làm việc với React, hãy xem xét stackoverflow.com/questions/41369497/
Khăn

Câu trả lời:


244

Sử dụng "đóng cửa":

$(edit_link).click(function(){ return changeViewMode(myvar); });

Điều này tạo ra một trình bao bọc hàm tạm thời ẩn danh biết về tham số và chuyển nó đến thực hiện gọi lại thực tế.


3
Nếu bạn muốn gọi một hàm trên một đối tượng, bạn cần gọi bind (). myObj.click (function () {this.doSthing ();} .bind (myObj)); Điều đó sẽ làm cho "cái này" trở thành myObj.
Eli

1
Đây không phải là một vấn đề hiệu suất khi xử lý nhiều trong số này? Ví dụ: Bạn đang hiển thị một onPress trong một hàng và bạn có 10.000 hàng. Điều này tạo ra một trình bao bọc hàm tạm thời ẩn danh mới cho mỗi Hàng. CÒn cách nào khác để thực hiện việc này không?
Joshua Pinter

@JoshuaPinter Bản thân kỹ thuật không phải là vấn đề. Nếu bạn cần cùng chức năng gọi 10.000 lần, bạn chỉ cần lưu trình bao bọc trong một biến, do đó bạn chỉ tạo một lần. Nếu bạn cần vượt qua 10.000 bối cảnh khác nhau, có rất ít bạn có thể làm. Cảnh giác với việc tối ưu hóa sớm: Như mọi khi với hiệu suất, bạn cần đo để xem có vấn đề gì hay không. Các công cụ JavaScript ngày nay rất mạnh mẽ và có thể tối ưu hóa mã theo những cách đáng ngạc nhiên.
Ferdinand Beyer

@FerdinandBeyer Tuyệt vời, cảm ơn vì tiền boa. Một người bạn nói với tôi rằng đó là một thực hành tồi và thay vào đó bạn nên sử dụng phương pháp this.myFunction = this.myFunction.bind(this)của mình constructor. Nhưng, như bạn đã nói, khi bạn phải chuyển các bối cảnh khác nhau cho từng bối cảnh, giống như tất cả các hàng khác nhau mà bạn nhấp vào để mở trang chi tiết của hàng đó, điều đó là không thể tránh khỏi.
Joshua Pinter

@FerdinandBeyer, cho phép nói myvar là một chuỗi và thay đổi của nó giữa hai lời gọi liên tiếp đi qua changeViewMode như một đóng cửa, nhưng changeViewMode luôn nhận giá trị đầu tiên của myvar, tôi muốn gọi chức năng đóng cửa với giá trị tham số khác nhau được gán cho biến cùng myvar,
nmxprime

42

Sử dụng Function.prototype.bind(). Trích dẫn MDN:

Các bind()phương pháp tạo ra một chức năng mới, khi được gọi, có nó thistập hợp từ khoá với giá trị cung cấp, với một chuỗi nhất định đối số trước bất kỳ cung cấp khi các chức năng mới được gọi.

Nó được hỗ trợ bởi tất cả các trình duyệt chính, bao gồm IE9 +.

Mã của bạn sẽ trông như thế này:

$(edit_link).click(changeViewMode.bind(null, myvar));

Lưu ý bên lề: Tôi giả sử bạn đang ở trong bối cảnh toàn cầu, tức là thisbiến là window; mặt khác sử dụng thisthay vì null.


Cảm ơn, điều này đã giúp tôi. Sử dụng nó như thế này:$.ajax(url).done(handler.bind(this, var1, var2));
Thomas

2
Lựa chọn nào là tốt nhất? Sử dụng đóng cửa hoặc sử dụng chức năng liên kết? Vui lòng cho tôi biết nếu có bất kỳ tác động hiệu suất nào
Varun


15

Không, nhưng bạn có thể vượt qua mà không cần tham số và thực hiện điều này:

$(edit_link).click(
  function() { changeViewMode(myvar); }
);

Vì vậy, bạn đang truyền một hàm ẩn danh không có tham số, hàm đó sẽ gọi hàm được tham số hóa của bạn với biến trong bao đóng



7

Hoặc nếu bạn đang sử dụng es6, bạn sẽ có thể sử dụng chức năng mũi tên

$(edit_link).click(() => changeViewMode(myvar));

2

Bạn có thể làm được việc này

var message  = 'Hello World';

var callback = function(){
alert(this)
}.bind(message);

và sau đó

function activate(callback){
  callback && callback();
}

activate(callback);

Hoặc nếu cuộc gọi lại của bạn chứa logic linh hoạt hơn, bạn có thể truyền đối tượng.

Bản giới thiệu


2

Đây là một ví dụ theo cách tiếp cận của Ferdinand Beyer:

function function1()
{
    function2(function () { function3("parameter value"); });
}
function function2(functionToBindOnClick)
{
    $(".myButton").click(functionToBindOnClick);
}
function function3(message) { alert(message); }

Trong ví dụ này, "giá trị tham số" được truyền từ function1 đến function3 qua function2 bằng cách sử dụng hàm bọc.

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.