2011-01-15 33 views
27

Tôi về cơ bản có một đối tượng, được mở rộng với hàm thông qua mẫu thử nghiệm của nó. Bên trong hàm đó, một hàm khác tồn tại, tuy nhiên khi sử dụng this trong hàm lồng nhau này, nó dường như không chỉ đến đối tượng, mà là hàm.'this' trong hàm bên trong hàm nguyên mẫu

Ví dụ,

var sampleObject = function() { 
this.foo = 123; 
} 

sampleObject.prototype.getFoo = function() { 
var nested = function() { 
    return this.foo; 
} 
return nested(); 
} 

var test = new sampleObject(); 

window.alert(test.getFoo()); // undefined 

Các this.foo không đề cập đến giá trị 123, nhưng không xác định vì điều này liên quan đến chức năng lồng nhau, trong đó không có foo tồn tại. Làm thế nào tôi có thể truy cập giá trị 123 từ hàm lồng nhau?

Cảm ơn.

+1

bản sao có thể có của [Trong Javascript, tại sao toán tử "này" không phù hợp?] (Http://stackoverflow.com/questions/80084/in-javascript-why-is-the-this-operator-inconsistent) –

Trả lời

30
sampleObject.prototype.getFoo = function() { 
var me = this; 
var nested = function() { 
    return me.foo; 
} 
return nested; 
} 

Bằng cách lưu giá trị của this trong một biến địa phương, bạn thực hiện nó một cách rõ ràng một phần của bối cảnh từ vựng cho chức năng đó và cho tất cả phạm vi chức năng lồng nhau. Do đó, khi gọi đến "lồng nhau", hàm bên trong đó sẽ có phạm vi riêng của nó (nó là giá trị this riêng), nhưng nó vẫn có thể tham chiếu đến biến "tôi" trong phạm vi kèm theo.

+0

và điều gì sẽ xảy ra nếu tôi làm: 'var foo = new sampleObject();' '$ (cửa sổ) .on ('scroll', foo.getFoo); ' – vsync

+0

@vsync sẽ ổn - nếu bạn' đang gặp vấn đề với một cái gì đó như thế, tôi đề nghị bạn mở một câu hỏi hoàn toàn mới với mẫu mã gây khó khăn. – Pointy

+1

nhưng điều đó không tốt, bởi vì bằng cách sử dụng một tham chiếu hàm, chúng ta mất 'this' rất quan trọng đối với việc tạo mẫu, vì vậy' var me = this; 'trong ví dụ của bạn sẽ trỏ đến' window' Object – vsync

8

Công việc chung quanh cho đó là sử dụng đóng

sampleObject.prototype.getFoo = function() { 
    var _this = this; 
    var nested = function() { 
    return _this.foo; 
    } 
    return nested(); 
} 

Một số thư viện thêm các phương pháp để tự động hóa này

+1

Tôi thích cách unautomated vì nó không phải là phức tạp, nhờ – pimvdb

+1

Bạn có thể thích nó trong tình huống này, nhưng cách tự động thực sự là tốt đẹp cho xử lý sự kiện. – Hemlock

0

Đây là một mụn cóc nổi tiếng trên JavaScript. Các mô hình thông thường là để gán điều này cho một biến (thường tự) trong các chức năng bên ngoài, sau đó truy cập tự từ funtction bên trong. Những công việc này.

3

Ngoài tuyên bố nó vào var _this = this, tôi cũng thấy mã đang thực hiện var that = this hoặc var self = this.

Biết phạm vi của biến là quan trọng vì nó có thể làm tăng kết quả không mong muốn.

+0

nếu bạn đang làm một dự án lớn đưa ra một quy ước. tức là luôn luôn sử dụng var that = this; hoặc bản thân hoặc cái gì là –

+0

Đối với tôi, 'đó' thường là biến trong một hàm nguyên mẫu, ví dụ: 'foo.prototype.add = function (đó) {return this + that}', vì vậy tôi thích 'self' hoặc' me'. – pimvdb

1

Đây là một câu hỏi cũ, nhưng tôi đưa ra một giải pháp khác vì mục đích hoàn chỉnh. Một cách tiếp cận khác liên quan đến function binding.

sampleObject.prototype.getFoo = function() { 
var nested = function() { 
    return this.foo; 
} 
return nested.bind(this)(); 
} 
+0

hey, đây là mát mẻ .. vì vậy .. bạn có thể xây dựng hiển thị một chức năng với một tham số .. Tôi có một cảm giác nó trông tương tự, nhưng .. khác nhau – bkwdesign

4

Trong ví dụ của bạn "này" dùng để chỉ đối tượng cửa sổ bởi vì bạn không nói rõ bối cảnh khác khi bạn gọi hàm lồng nhau và bạn sẽ có được undefind vì window.foo là undefined.

Bạn có thể sửa lỗi này theo 3 cách.

1 - Sử dụng một biến để lưu trữ bên ngoài này - sử dụng nhiều nhất phương pháp

sampleObject.prototype.getFoo = function() { 
var _this = this; 
var nested = function() { 
    return _this.foo; 
} 
return nested(); 
} 

2 - Sử dụng các phương pháp ràng buộc mà ràng buộc bên ngoài "này" vào bên trong một

sampleObject.prototype.getFoo = function() { 
var nested = function() { 
    return this.foo; 
}.bind(this); 
return nested(); 
} 

3 - Sử dụng phương thức gọi có thể chuyển ngữ cảnh đến hàm

SampleObject.prototype.getFoo = function() { 
var nested = function() { 
    return this.foo; 
}; 
return nested.call(this); 
} 
0

tl; dr

Sử dụng arrow functions. Họ có sẵn từ ECMAScript 6:

var sampleObject = function() { 
 
    this.foo = 123; 
 
} 
 

 
sampleObject.prototype.getFoo = function() { 
 
    var nested =() => { // Changed this line. 
 
    return this.foo; 
 
    } 
 
    return nested(); 
 
} 
 

 
var test = new sampleObject(); 
 

 
window.alert(test.getFoo());

Giải thích

Đây là một trong những ưu điểm chính của chức năng mũi tên. Trường hợp của bạn được mô tả trong phần: No binding of this. Các trạng thái refference:

Cho đến chức năng mũi tên, mỗi chức năng mới được xác định giá trị this riêng của mình [...] Một mũi tên hàm không tạo this bối cảnh riêng của mình, vì vậy this có ý nghĩa ban đầu từ bối cảnh kèm theo.

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