2016-12-30 16 views
29

Sự cố trong ví dụ 1 là 'this' đề cập đến tên chung thay vì đối tượng myName.Tại sao phải liên kết JavaScript()?

Tôi hiểu việc sử dụng bind() trong việc đặt giá trị của giá trị này cho một đối tượng cụ thể, vì vậy nó giải quyết được vấn đề trong ví dụ 1, nhưng tại sao vấn đề này lại xảy ra ngay từ đầu? Nó chỉ là cách Javascript được tạo ra?

Tôi cũng tự hỏi tại sao ví dụ 3 giải quyết vấn đề và sự khác biệt giữa các ví dụ 2 và 3.

this.name = "John" 
 

 
var myName = { 
 
    name: "Tom", 
 
    getName: function() { 
 
    return this.name 
 
    } 
 
} 
 

 
var storeMyName = myName.getName; // example 1 
 
var storeMyName2 = myName.getName.bind(myName); // example 2 
 
var storeMyName3 = myName.getName(); // example 3 
 

 
console.log("example 1: " + storeMyName()); // doesn't work 
 
console.log("example 2: " + storeMyName2()); // works 
 
console.log("example 3: " + storeMyName3); // works

+2

* "Có phải nó chỉ là cách Javascript đã được tạo ra?" * Tôi đoán có. Giá trị của 'this' được xác định động, trừ khi nó là một hàm ràng buộc hoặc một mũi tên. Không chắc bạn muốn biết điều gì khác nữa [tìm hiểu về cách thức hoạt động của tính năng này] (https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes /ch1.md). –

+0

Có thể trùng lặp của [Javascript call() & apply() vs bind()?] (Http://stackoverflow.com/questions/15455009/javascript-call-apply-vs-bind) – azad

+3

* "Tôi cũng tự hỏi tại sao ví dụ 3 giải quyết vấn đề "*' storeMyName' và 'storeMyName2' chứa * functions * trong khi' storeMyName3' chứa * kết quả * của * gọi * 'myName.getName()'. Sự khác biệt lớn. Tôi đã thực hiện so sánh này giữa các cách gọi một hàm và '.bind': https://twitter.com/fkling42/status/736228742008176640. Có lẽ nó giúp bằng cách nào đó. –

Trả lời

51

Tại sao phải liên kết JavaScript()?

Giá trị của this được xác định bởi cách một chức năng là gọi. Nếu đó là bạn, người gọi hàm này thì thường không cần sử dụng .bind, vì bạn có quyền kiểm soát cách gọi hàm và do đó giá trị this của nó.

Tuy nhiên, thường là không phải bạn gọi hàm này. Các hàm được chuyển đến các hàm khác như gọi lại và xử lý sự kiện. Chúng được gọi bằng mã số khác và bạn không kiểm soát được cách chức năng được gọi là và do đó không thể kiểm soát nội dung this sẽ tham chiếu.

Nếu chức năng của bạn yêu cầu this được đặt thành giá trị cụ thể và bạn không phải là người đang gọi hàm, bạn cần phải .bind chức năng với giá trị this cụ thể.

Nói cách khác: .bind cho phép bạn đặt giá trị this mà không cần gọi hàm bây giờ.

Dưới đây là so sánh các đề cập đến/chức năng gọi số:

    +-------------------+-------------------+ 
        |     |     | 
        |  time of  |  time of  | 
        |function execution | this binding | 
        |     |     | 
+-------------------+-------------------+-------------------+ 
|     |     |     | 
| function object |  future  |  future  | 
|   f   |     |     | 
|     |     |     | 
+-------------------+-------------------+-------------------+ 
|     |     |     | 
| function call |  now   |  now  | 
|  f()  |     |     | 
|     |     |     | 
+-------------------+-------------------+-------------------+ 
|     |     |     | 
|  f.call()  |  now   |  now  | 
|  f.apply()  |     |     | 
|     |     |     | 
+-------------------+-------------------+-------------------+ 
|     |     |     | 
|  f.bind()  |  future  |  now  | 
|     |     |     | 
+-------------------+-------------------+-------------------+ 

Tôi cũng tự hỏi tại sao ví dụ 3 giải quyết vấn đề và sự khác biệt giữa các ví dụ 2 và 3.

Ví dụ 1/2 và 3 không thể khác hơn. storeMyNamestoreMyName2 chứa chức năng, được gọi trong tương lai, trong khi storeMyName3 chứa kết quả gọi myName.getName()tại thời điểm đó.


Tiếp tục đọc tài liệu:

+0

cảm ơn rất nhiều sự giúp đỡ và tài nguyên của bạn. Tôi mới vào javascript và bạn đã thực hiện câu trả lời rất rõ ràng đối với tôi. Vì vậy, gọi()/apply() là giống như ví dụ 3, ngoại trừ được sử dụng khi phương thức getName() tách biệt khỏi đối tượng? –

+0

Về cơ bản có. Nếu một hàm là thuộc tính của một đối tượng, sau đó gọi hàm là 'myName.getName()' sẽ ngầm đặt 'this' thành' myName'. Nó tương đương với 'myName.getName.call (myName)'. –

5

Phương pháp bind() tạo một hàm mới đó, khi gọi , có từ khóa này được đặt thành giá trị được cung cấp, với một chuỗi các đối số đã cho trước bất kỳ khi nào hàm mới được gọi.

Vì vậy, khi bạn thực hiện var storeMyName = myName.getName; lần đầu tiên, phải mất toàn cầu name (this.name = "John")

Khi bạn sử dụng chức năng bind(), nó bắt đầu đề cập đến tên được định nghĩa trong hiện tại đóng cửa (Myname trong trường hợp này) và do đó in Tom

thời gian thứ ba, kể từ khi hàm được gọi ngay lập tức phạm vi của nó nằm trong đối tượng địa phương riêng của mình và do đó sẽ in giá trị trong việc đóng cửa Tom

0

Bind là cơ chế mà qua đó bạn có thể thay đổi ngữ cảnh (ở đây ngữ cảnh mặc định của bạn là toàn cục) của việc thực hiện.

Dựa trên ví dụ của bạn -

var storeMyName = myName.getName; 

Từ dòng trên là bạn đang thực hiện storeMyName chức năng trong bối cảnh toàn cầu, vì vậy để thực hiện này this.name sẽ dòng trên cùng (nghĩa là một thế giới/"John".).

var storeMyName2 = myName.getName.bind(myName); 

Đối với dòng trên bạn Rõ ràng thay đổi bối cảnh thực hiện cho storeMyName2 chức năng (bằng cách nói rằng tôi không muốn thực hiện chức năng này như chức năng toàn cầu tôi muốn thực hiện chức năng này trong bối cảnh myName đối tượng , vì vậy trong trường hợp này this.name sẽ là "Tom")

var storeMyName3 = myName.getName(); // example 3 

Và đối với dòng trên này bạn chỉ thực hiện chức năng trên myName bối cảnh đối tượng, quan trọng hơn là bạn không thực hiện các storeMyName3 và đó là lý do tại sao ngữ cảnh của nó không phải là bối cảnh toàn cầu.

0

Tương tự tôi thích, mà tôi chưa bao giờ thấy ở bất kỳ đâu: Giả sử bạn có đối tượng foo với hàm bar. Khi bạn liên kết hàm bar với biến khác (hoặc chuyển nó thành tham số hàm, trường hợp phổ biến hơn với callbacks), bạn không ràng buộc/truyền hàm với đối tượng kèm theo của mình nhưng chỉ có hàm "khỏa thân". Do đó với chức năng "khỏa thân", this có nghĩa là đối tượng chung.

Một bản demo nhỏ

var foo = "global foo"; //foo set on the global object 
var a = {foo : "object foo", bar : function(){return this.foo;}}; 
var bound = a.bar; 
console.log(bound());//returns "global foo", not "object foo" 

bound chỉ trỏ đến function(){return this.foo;}

Các vấn đề liên quan