2010-10-25 20 views
42

Tôi mới sử dụng JavaScript. Mới như xa như tất cả tôi đã thực sự thực hiện với nó là tinh chỉnh mã hiện tại và đã viết các bit nhỏ của jQuery.'this' không được xác định trong các phương thức lớp JavaScript

Bây giờ tôi đang cố gắng viết một "lớp" với các thuộc tính và phương pháp, nhưng tôi đang gặp rắc rối với các phương pháp. Mã của tôi:

function Request(destination, stay_open) { 
    this.state = "ready"; 
    this.xhr = null; 
    this.destination = destination; 
    this.stay_open = stay_open; 

    this.open = function(data) { 
     this.xhr = $.ajax({ 
      url: destination, 
      success: this.handle_response, 
      error: this.handle_failure, 
      timeout: 100000000, 
      data: data, 
      dataType: 'json', 
     }); 
    }; 

    /* snip... */ 

} 

Request.prototype.start = function() { 
    if(this.stay_open == true) { 
     this.open({msg: 'listen'}); 
    } else { 

    } 
}; 
//all console.log's omitted 

Vấn đề là, trong Request.prototype.start, this là undefined và do đó câu lệnh if là false. Tôi làm gì sai ở đây?

+0

Có lý do nào bạn có 'bắt đầu' trong' nguyên mẫu' không? – xj9

+0

Cài đặt 'Request.prototype' là gì? –

+0

Tôi không có ý kiến: S –

Trả lời

43

Bạn gọi chức năng khởi động như thế nào?

này nên làm việc (mới là chìa khóa)

var o = new Request(destination, stay_open); 
o.start(); 

Nếu bạn trực tiếp gọi nó như Request.prototype.start(), this sẽ đề cập đến bối cảnh toàn cầu (window trong các trình duyệt).

Ngoài ra, nếu this không xác định, điều này dẫn đến lỗi. Biểu thức if không đánh giá sai.

Cập nhật: this đối tượng không được thiết lập dựa trên tuyên bố, nhưng bởi gọi. Điều đó có nghĩa là nếu bạn gán thuộc tính chức năng cho một biến như x = o.start và gọi x(), this bên trong bắt đầu không còn đề cập đến o. Đây là những gì sẽ xảy ra khi bạn làm setTimeout. Để làm cho nó hoạt động, hãy thực hiện việc này thay thế:

var o = new Request(...); 
setTimeout(function() { o.start(); }, 1000); 
+0

Tôi đang sử dụng setTimeout: 'var listen = new Request (đích, stay_open); setTimeout (listen.start, 500); ' –

+0

Có, điều đó sẽ không hoạt động. Tôi sẽ cập nhật câu trả lời của mình. –

+0

tuyệt vời, cảm ơn bạn –

15

OOP của JavaScript là một chút sôi nổi (hoặc rất nhiều) và cần phải làm quen. Điều đầu tiên bạn cần lưu ý là không có Lớp học nào và suy nghĩ về các lớp học có thể giúp bạn đi lên. Và để sử dụng một phương thức gắn liền với một Constructor (tương đương với JavaScript của một định nghĩa lớp), bạn cần phải khởi tạo đối tượng của mình. Ví dụ:

Ninja = function (name) { 
    this.name = name; 
}; 
aNinja = new Ninja('foxy'); 
aNinja.name; //-> 'foxy' 

enemyNinja = new Ninja('boggis'); 
enemyNinja.name; //=> 'boggis' 

Lưu ý rằng Ninja trường hợp có tính chất tương tự nhưng aNinja không thể truy cập các thuộc tính của enemyNinja. (Phần này nên thực sự dễ dàng/đơn giản) Mọi thứ trở nên một chút khác nhau khi bạn bắt đầu thêm công cụ để các prototype:

Ninja.prototype.jump = function() { 
    return this.name + ' jumped!'; 
}; 
Ninja.prototype.jump(); //-> Error. 
aNinja.jump(); //-> 'foxy jumped!' 
enemyNinja.jump(); //-> 'boggis jumped!' 

Calling này trực tiếp sẽ ném ra một lỗi vì this chỉ trỏ tới đối tượng đúng (bạn "Class ") khi Constructor được khởi tạo (nếu không nó trỏ đến đối tượng toàn cầu, window trong trình duyệt)

3

Trong ES2015 aka ES6, class là một đường cú pháp cho functions.

Nếu bạn muốn bắt buộc đặt ngữ cảnh cho this, bạn có thể sử dụng phương thức bind(). Như @chetan đã chỉ ra, về việc gọi bạn cũng có thể thiết lập bối cảnh!Kiểm tra ví dụ bên dưới:

class Form extends React.Component { 
constructor() { 
    super(); 
    } 
    handleChange(e) { 
    switch (e.target.id) { 
     case 'owner': 
     this.setState({owner: e.target.value}); 
     break; 
     default: 
    } 
    } 
    render() { 
    return (
     <form onSubmit={this.handleNewCodeBlock}> 
     <p>Owner:</p> <input onChange={this.handleChange.bind(this)} /> 
     </form> 
    ); 
    } 
} 

Ở đây chúng tôi đã buộc ngữ cảnh bên trong .

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