2011-11-29 46 views
6

thể trùng lặp:
In Javascript, why is the “this” operator inconsistent?lớp javascript biến phạm vi trong hàm callback

Tôi có lớp sau đây:

function Chat(some, nick, url) { 
    this.socket = null; 
    this.Nickname = nick; 
    this.Url = url; 

    this.Connect = function() { 
     socket = io.connect(this.Url); 
     socket.on('connect', function (data) { 
      var p = this.Nickname; //this.Nickname is undefined why? 
      // how can I acess to the Nickname variable or function? 
     } 
    }; 
} 

Làm thế nào tôi có thể acces biến cá thể hoặc chức năng từ chức năng gọi lại kết nối?

+1

Trên 'this.Connect', bạn sẽ có thể thực hiện' var obj = this; 'và sau đó sử dụng biến đó trong hàm. – Danny

+0

Cảm ơn tất cả những người đang chờ bạn! có tất cả chính xác! nhưng tôi chỉ có thể chọn một. – elranu

Trả lời

26

Giải pháp đơn giản nhất là sử dụng that lừa

var that = this; //that is a normal variable 
       //so it is lexically scoped 
       //and can be used in inner functions 

socket.on('connect', function(data){ 
    var p = that.NickName; 
}); 

Một khả năng khác là rõ ràng mới ràng buộc chính xác này đến hàm callback

socket.on('connect', function(data){ 
    var p = this.Nickname; 
}.bind(this)); 

Bí quyết that có lợi thế là làm tổ cho càng nhiều callbacks như bạn muốn và phiên bản bind có lợi thế là cho phép bạn vẫn sử dụng "this" bên trong.

Một bất lợi của phương pháp liên kết là nó không được hỗ trợ trong IE < = 8, do đó bạn có thể cần phải sử dụng một shim nếu bạn cần hỗ trợ các trình duyệt cũ.

chỉnh sửa: Câu trả lời này hơi cũ. Ngày nay bạn có thể không cần phải lo lắng về IE6 nữa và bạn có thể sử dụng fat arrow syntax, không ghi đè lên this.

+4

Một cái gì đó cần lưu ý về phương thức bind() là, vì bạn đang ở node.js (và bạn biết công cụ Javascript của mình), bạn biết rằng V8 có một số tính năng ECMAScript 5 được triển khai trong nó (https://github.com/ joyent/node/wiki/ECMA-5-Mozilla-Tính năng-Triển khai-in-V8), bạn thực sự có hàm bind() và có thể sử dụng nó một cách an toàn! :) – RyanWilcox

2

Vấn đề là giá trị this trong javascript có thể thay đổi tùy thuộc vào cách gọi lại được gọi. Cách dễ nhất để giải quyết vấn đề này là lưu đối tượng this gốc thành một địa phương có tên là self. Địa phương được ghi lại trong cuộc gọi lại và có thể được sử dụng để truy cập các giá trị thành viên. Ví dụ.

function Chat(some, nick, url) { 
    var self = this; 
    this.socket = null; 
    this.Nickname = nick; 
      this.Url = url; 

    this.Connect = function() { 
     socket = io.connect(this.Url); 
     socket.on('connect', function (data) { 
      var p = self.Nickname; //this.Nickname is undifined why? 
      // how can I acess to the Nickname variable or function? 
     } 
    }; 
    } 
2

Bạn có thể thay đổi điều này: var p = this.Nickname; để var p = nick;

Vấn đề của bạn này là this đề cập đến phạm vi địa phương của hàm bạn đang sử dụng trong callback. Nó không phải là phạm vi của hàm bên ngoài.

1

"this" đại diện cho chức năng của bạn trong phạm vi đó.

thử:

function Chat(some, nick, url) { 
    this.socket = null; 
    this.Nickname = nick; 
     this.Url = url; 

    var that = this; 

    this.Connect = function() { 
     socket = io.connect(this.Url); 
     socket.on('connect', function (data) { 
      var p = that.Nickname; //this.Nickname is undifined why? 
      // how can I acess to the Nickname variable or function? 
     } 
    }; 
} 

Lưu ý việc chuyển nhượng "này" thành "rằng"

+0

Có 'this' thực sự đại diện cho * chức năng *? Tôi nghĩ nó đại diện cho * người gọi *? –

+0

Thats một câu hỏi hay, bạn biết đấy, tôi không chắc chắn nếu nó đại diện cho người gọi, hoặc đối tượng mà phương pháp này là một thành viên của. trong mọi trường hợp, bạn đúng, nó không đại diện cho hàm bên trong. –

+0

@Uzi: Javascript này được đặt tùy thuộc vào cách chức năng được gọi. Nếu bạn làm f() thì điều này sẽ không xác định hoặc đối tượng chung. Nếu bạn làm obj.f(), đây sẽ là obj và cuối cùng bạn cũng có thể sử dụng tùy chọn này với f.call (myThis, 1, 2) hoặc f.apply. Chức năng làm * không * biết "class" chúng là gì và 'this' là wholy promiscuous. – hugomg

1

JavaScript có đóng cửa đó là, để nói rằng ít nhất, tiện lợi.

Có xem xét câu hỏi này:

How do JavaScript closures work?

Nó sẽ giúp bạn hiểu tại sao tất cả mọi người là nói cho bạn để đặt một var something = this trên chức năng và sử dụng something bên trong của nó để duy trì một tham chiếu với bản gốc this.

1

Dưới đây là một fiddle đó cho thấy sử dụng bản sao cục bộ này:

http://jsfiddle.net/k7vC6/1/

Trong trường hợp đó, thisself là những điều tương tự, nhưng sử dụng self là an toàn.

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