2015-06-28 34 views
5

Tôi đang cố gắng để hiểu rõ hơn this Firebase authenticator for Ember SimpleAuth:Điều gì sẽ xảy ra khi bạn liên kết 'this' với chức năng Ember?

import Ember from 'ember'; 


export default Ember.Controller.extend({ 


actions: { 
    login: function() { 
     this.get('session').authenticate('authenticator:firebase', { 
      'email': this.get('email'), 
      'password': this.get('password') 
     }).then(function() { 
      this.transitionToRoute('index'); 
     }.bind(this)); 
    }, 
    logout: function() { 
     this.get('session').invalidate().then(function() { 
      this.transitionToRoute('login'); 
     }.bind(this)); 
    } 
} 
}); 

có ai đó hãy giải thích những gì ".bind (this)" đang làm và ràng buộc đang làm việc như thế nào một cách chính xác trong trường hợp đặc biệt này?

Edit: Sau khi một sự phản ánh ít và nghiên cứu, đây là lời giải thích đề xuất của tôi về những gì có thể xảy ra:

Các ".Sau đó" của mã không có quyền truy cập vào bối cảnh ban đầu của 'này'. ".bind (this)" đặt giá trị của "this" (trong trường hợp này là đối tượng điều khiển hiện tại) thành "this" bên trong hàm ".then".

Điều này có thể được chứng minh bằng thực tế là nếu phần ".bind (this)" bị xóa, phần "transitionTo" của mã không hoạt động.

Mặt khác, nếu chúng ta viết mã như sau, chúng tôi không cần phải sử dụng ".bind (this)":

import Ember from 'ember'; 


export default Ember.Controller.extend({ 


actions: { 
    login: function() { 
    var _this = this; 
     this.get('session').authenticate('authenticator:firebase', { 
      'email': this.get('email'), 
      'password': this.get('password') 
     }).then(function() { 
      _this.transitionToRoute('index'); 
     }); 
    }, 
    logout: function() { 
     var _this = this; 
     this.get('session').invalidate().then(function() { 
      _this.transitionToRoute('login'); 
     }); 
    } 
} 


}); 

Suy nghĩ?

+0

Đúng, bạn nên thêm phần cuối bài đăng của mình làm câu trả lời (bạn có thể trả lời câu hỏi của riêng mình). – steveax

Trả lời

9

Điều gì sẽ xảy ra khi bạn liên kết 'this' với chức năng Ember?

Trong ví dụ của bạn, .bind() không được sử dụng cho chức năng Ember. Nó được sử dụng trên các hàm ẩn danh thông thường (gọi lại). Do đó, câu hỏi của bạn không liên quan gì đến Ember.

Bằng cách gọi lại, tôi có nghĩa là một hàm ẩn danh được truyền dưới dạng đối số thay vì được gán cho thuộc tính của đối tượng.

Chức năng như vậy sẽ bị ràng buộc với window, i. e. this trong hàm sẽ trả về window.

Một cách tiếp cận truyền thống tiếp cận phạm vi bên ngoài được gán this cho một biến trong một phạm vi bên ngoài, sau đó truy cập vào biến trong phạm vi nội:

var _this = this; 

someMethod(function() { 
    console.log(this); // => window 
    console.log(_this); // => Outer scope 
}); 

Cách tiếp cận này là tốt khi bạn cần truy cập vào cả hai bên và phạm vi bên ngoài. Nhưng không có gì hữu ích trong phạm vi nội là, vì vậy chúng tôi có thể viết nó ngắn hơn:

someMethod(function() { 
    console.log(this); // Outer scope 
}.bind(this)); 

Phương pháp .bind() được thực hiện trong phạm vi bên ngoài vào chức năng anon. Nó liên kết hàm với phạm vi bên ngoài. Do đó, phạm vi bên trong của hàm sẽ giống như phạm vi bên ngoài và bạn có thể sử dụng this như thường lệ, như thể phạm vi không thay đổi.

Trong CoffeeScript, bạn có thể sử dụng mũi tên béo ở lại trong phạm vi bên ngoài:

_this = this 

someMethod -> 
    console.log this # winodw 
    console.log _this # Outer scope 
someMethod => 
    console.log this  # Outer scope 
    console.log ` this ` # You can still access window like ` this `, pun intended 

Trong ES6 bạn có thể sử dụng mũi tên béo quá:

foo(() => { 
    console.log(this); 
}); 

ý rằng mặc dù như trong CoffeeScript, mũi tên béo duy trì phạm vi bên ngoài, nó có nghĩa là một điều khác! Trong ES6, mũi tên chất béo tạo ra một hàm giả không thể có phạm vi riêng của nó.

Điều này quan trọng vì một số thư viện liên lạc với một cuộc gọi lại bằng cách áp dụng gọi lại đến một phạm vi nhất định và mong đợi bạn làm this.something() trên đó. Nó sẽ không hoạt động với mũi tên chất béo ES6 (tốt, nó có thể làm việc kỹ thuật với Babel vì Babel chuyển đổi mũi tên chất béo ES6 thành các chức năng truyền thống, nhưng bạn không nên dựa vào đó).

Để biết thêm thông tin về .bind(), hãy xem Function.prototype.bind() on MDN.

+0

giải thích siêu rõ ràng. cảm ơn. – learningMachine

+0

. Tôi đã chấp nhận và bỏ phiếu. – learningMachine

3

Đó chính xác là những gì đang xảy ra. Nếu bạn .bind (điều này) thì bạn không cần phải tạo bí danh cho bên ngoài chức năng này. Xem this question để được giải thích thêm.

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