Đặt ra biến này có thể dễ dàng?


139

Tôi có một sự hiểu biết khá tốt về Javascript, ngoại trừ việc tôi không thể tìm ra một cách hay để đặt biến "này". Xem xét:

var myFunction = function(){
    alert(this.foo_variable);
}

var someObj = document.body; //using body as example object
someObj.foo_variable = "hi"; //set foo_variable so it alerts

var old_fn = someObj.fn;   //store old value
someObj.fn = myFunction;   //bind to someObj so "this" keyword works
someObj.fn();              
someObj.fn = old_fn;       //restore old value

Có cách nào để làm điều này mà không có 4 dòng cuối cùng? Điều đó khá khó chịu ... Tôi đã thử ràng buộc một chức năng ẩn danh, điều mà tôi nghĩ là đẹp và thông minh, nhưng không có kết quả:

var myFunction = function(){
    alert(this.foo_variable);
}

var someObj = document.body;        //using body as example object
someObj.foo_variable = "hi";        //set foo_variable so it alerts
someObj.(function(){ fn(); })();    //fail.

Rõ ràng, chuyển biến vào myFactor là một tùy chọn ... nhưng đó không phải là điểm của câu hỏi này.

Cảm ơn.

Câu trả lời:


221

Có hai phương thức được định nghĩa cho tất cả các hàm trong JavaScript call()apply(). Cú pháp hàm trông như sau:

call( /* object */, /* arguments... */ );
apply(/* object */, /* arguments[] */);

Những gì các hàm này làm là gọi hàm mà chúng được gọi, gán giá trị của tham số đối tượng này .

var myFunction = function(){
    alert(this.foo_variable);
}
myFunction.call( document.body );

3
Ngoài ra, nếu bạn đang sử dụng jQuery, bạn có thể sử dụng $.proxy(function, element)để bất cứ khi nào hàm đó được gọi, nó sẽ nằm trong ngữ cảnh của phần tử. api.jquery.com/jquery.proxy
Trevin Avery

Một phương pháp hữu ích khác là.bind()
Soroush Falahati

55

Tôi nghĩ bạn đang tìm kiếm call:

myFunction.call(obj, arg1, arg2, ...);

Cuộc gọi này myFunctionvới thiscác thiết lập để obj.

Ngoài ra còn có phương thức hơi khác apply, lấy tham số hàm làm mảng:

myFunction.apply(obj, [arg1, arg2, ...]);

1
Xem phần 15.3.4.3, 15.3.4.4 và 10.1.8 trong Đặc tả ngôn ngữ ECMAScript: ecma
một số

18

Nếu bạn muốn 'lưu trữ' thisgiá trị cho một hàm để sau này bạn có thể gọi nó một cách liền mạch (ví dụ: khi bạn không có quyền truy cập vào giá trị đó nữa), bạn có thể bind(mặc dù không có sẵn trong tất cả các trình duyệt):

var bound = func.bind(someThisValue);

// ... later on, where someThisValue is not available anymore

bound(); // will call with someThisValue as 'this'

7
FYI bindrõ ràng có sẵn trong IE9 +, FF4 +, Safari 5.1.4+ và Chrome 7+ (nguồn) . Bạn cũng có thể gọi liên kết trực tiếp trên một chức năng ẩn danh:var myFunction = function(){ /* this = something */ }.bind(something);
Adam

1

Tìm kiếm của tôi về cách liên kết thisđã đưa tôi đến đây vì vậy tôi đang đăng những phát hiện của mình: Trong 'ECMAScript 2015', chúng tôi cũng có thể thiết lập từ vựng này bằng cách sử dụng các hàm mũi tên.

Xem: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Fifts/Arrow_fifts

Thay vì:

function Person() {
  setInterval(function growUp() {
    // The callback refers to the `self` variable of which
    // the value is the expected object.
    this.age++;
  }.bind(this), 1000);
}

Bây giờ chúng ta có thể làm:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();

0

Đặt thistừ khóa trong javascript.

Javascript có 3 phương thức tích hợp để thiết lập thistừ khóa một cách thuận tiện. Tất cả chúng đều nằm trên Function.prototypeđối tượng để mọi chức năng đều có thể sử dụng chúng (vì mọi chức năng đều kế thừa từ nguyên mẫu này thông qua kế thừa nguyên mẫu). Các chức năng này như sau:

  1. Function.prototype.call(): Hàm này lấy đối tượng mà bạn muốn sử dụng làm thisđối số đầu tiên. Sau đó, phần còn lại của các đối số là các đối số tương ứng của hàm được gọi.
  2. Function.prototype.apply(): Hàm này lấy đối tượng mà bạn muốn sử dụng làm thisđối số đầu tiên. Sau đó, đối số thứ hai là một mảng chứa các giá trị của các đối số của hàm được gọi (phần tử đầu tiên của mảng là đối số thứ nhất của hàm, đối số thứ hai của mảng là đối số thứ hai của hàm, v.v.).
  3. Function.prototype.bind(): Hàm này trả về một hàm mới có giá trị khác this. Nó lấy đối tượng mà bạn muốn đặt làm thisgiá trị làm đối số đầu tiên và sau đó trả về một đối tượng hàm mới.

Sự khác biệt giữa cuộc gọi / áp dụng và ràng buộc:

  • callapplytương tự trong thực tế là họ gọi hàm ngay lập tức (với giá trị được xác định trước là this)
  • bindkhác với callapplytrong thực tế là hàm này trả về một hàm mới với một ràng buộc khác của thisgiá trị.

Ví dụ:

const thisObj = {
  prop1: 1,
  prop2: 2,
};

function myFunc(arg1, arg2) {
  console.log(this.prop1, this.prop2);
  console.log(arg1, arg2);
}

// first arg this obj, other arguments are the  
// respective arguments of the function
myFunc.call(thisObj, 'Call_arg1', 'Call_arg2');

// first arg this obj, other argument is an array which  
// are the respective arguments of the function
myFunc.apply(thisObj, ['Apply_arg1', 'Apply_arg2']);


// the bind method returns a new function with a different
// this context which is stored in the newMyFunc variable
const newMyFunc = myFunc.bind(thisObj);

// now we can call the function like a normal function 
newMyFunc('first', 'second');

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.