Làm thế nào để tôi chuyển bối cảnh này đến một chức năng?


213

Tôi nghĩ rằng đây sẽ là thứ tôi có thể dễ dàng google, nhưng có lẽ tôi không hỏi đúng câu hỏi ...

Làm cách nào để đặt bất cứ thứ gì "này" đề cập đến trong một hàm javascript cụ thể?

ví dụ, như với hầu hết các hàm của jQuery như:

$(selector).each(function() {
   //$(this) gives me access to whatever selector we're on
});

Làm cách nào để tôi viết / gọi các hàm độc lập của riêng mình có tham chiếu "này" thích hợp khi được gọi? Tôi sử dụng jQuery, vì vậy nếu có cách làm cụ thể của jQuery, thì đó là lý tưởng.


Bản sao có thể có: stackoverflow.com/questions/520019/
Ấn

Tôi biết đây là một câu hỏi cũ, nhưng đối với những người khác hạ cánh ở đây, hãy xem jQuery$.proxy
RyBolt

Câu trả lời:


302

Javascripts .call().apply()phương thức cho phép bạn đặt bối cảnh cho một hàm.

var myfunc = function(){
    alert(this.name);
};

var obj_a = {
    name:  "FOO"
};

var obj_b = {
    name:  "BAR!!"
};

Bây giờ bạn có thể gọi:

myfunc.call(obj_a);

Mà sẽ cảnh báo FOO. Cách khác, đi qua obj_bsẽ cảnh báo BAR!!. Sự khác biệt giữa .call().apply().call()có một danh sách được phân tách bằng dấu phẩy nếu bạn truyền đối số cho hàm của mình và .apply()cần một mảng.

myfunc.call(obj_a, 1, 2, 3);
myfunc.apply(obj_a, [1, 2, 3]);

Do đó, bạn có thể dễ dàng viết một hàm hookbằng cách sử dụng apply()phương thức. Chẳng hạn, chúng tôi muốn thêm một tính năng cho .css()phương thức jQuery . Chúng ta có thể lưu trữ tham chiếu chức năng ban đầu, ghi đè chức năng bằng mã tùy chỉnh và gọi chức năng được lưu trữ.

var _css = $.fn.css;
$.fn.css = function(){
   alert('hooked!');
   _css.apply(this, arguments);
};

argumentsđối tượng ma thuật là một mảng giống như đối tượng, chúng ta có thể chuyển nó tới apply(). Bằng cách đó, chúng tôi đảm bảo rằng tất cả các tham số được truyền qua chức năng ban đầu.


4
Chỉ là một mẩu tin vui: obj_aví dụ, nếu bạn cần gọi hàm liên tục để tham khảo , bạn có thể tạo một bản sao của nó var boud_myfunc = myfunc.bind(obj_a)và chỉ cần gọi bound_myfunc()khi cần.
wbadart

44

Sử dụngfunction.call :

var f = function () { console.log(this); }
f.call(that, arg1, arg2, etc);

Đâu thatlà đối tượng mà bạn muốn thistrong hàm.


1
functionlà một từ khóa dành riêng; xem xét cập nhật phản hồi của bạn để bao gồm một hàm được đặt tên vì function.call(...)JavaScript không hợp lệ.
Daniel Allen

1
@Daniel ALLen: Không có định nghĩa về bất kỳ tên hàm mẫu nào tôi sẽ cung cấp, mã vẫn sẽ gây ra lỗi JS. Nhưng, tôi đã cập nhật tên hàm mẫu.
palswim

16

jQuery sử dụng một .call(...)phương thức để gán nút hiện tại cho thisbên trong hàm bạn truyền làm tham số.

BIÊN TẬP:

Đừng ngại nhìn vào mã của jQuery khi bạn nghi ngờ, tất cả đều ở dạng Javascript rõ ràng và được ghi chép rõ ràng.

tức là: câu trả lời cho câu hỏi này là khoảng dòng 574,
callback.call( object[ name ], name, object[ name ] ) === false


12

Bạn có thể sử dụng chức năng liên kết để đặt bối cảnh thisbên trong một chức năng.

function myFunc() {
  console.log(this.str)
}
const myContext = {str: "my context"}
const boundFunc = myFunc.bind(myContext);
boundFunc(); // "my context"

12

Một ví dụ cơ bản khác:

Không làm việc:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
};
img.src = reader.result;

Đang làm việc:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
}.bind(this);
img.src = reader.result;

Về cơ bản: chỉ cần thêm .bind (this) vào hàm của bạn


Đây phải là câu trả lời được chấp nhận. Cú pháp dễ dàng hơn nhiều, dễ dàng hơn nhiều trong tâm trí ... công việc tốt Joery
nenea
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.