Làm việc như thế này bởi vì mỗi hàm đã liên kết ngữ cảnh thực thi riêng của mình.
Tuy nhiên có những cách khác để làm điều đó, ví dụ:
Sử dụng call
hoặc apply
để gọi hàm:
function Alpha() {
this.onion = 'onion';
function Beta() {
alert(this.onion);
}
Beta.call(this);
}
var alpha1 = new Alpha();
// Alerts 'onion'
mới ECMAScript 5 Standard Edition, giới thiệu một cách để kéo dài chức năng bối cảnh, các Function.prototype.bind
phương pháp:
function Alpha() {
this.onion = 'onion';
var Beta = function() {
alert(this.onion);
}.bind(this);
Beta();
}
var alpha1 = new Alpha();
// Alerts 'onion'
Có thể nói rằng hàm Beta
là bị ràng buộc và bất kể bạn gọi nó như thế nào, giá trị this
của nó sẽ là nguyên vẹn.
Phương pháp này chưa được hỗ trợ rộng rãi, hiện tại chỉ có IE9pre3 bao gồm nó, nhưng bạn có thể bao gồm an implementation để làm cho nó hoạt động ngay bây giờ.
Bây giờ hãy để tôi xây dựng về cách this
công trình:
Giá trị this
tồn tại trên mỗi execution context, và cho Mã hàm được thiết lập ngầm khi một cuộc gọi chức năng được thực hiện, giá trị được xác định tùy thuộc cách tham khảo nếu hình thành.
Trong ví dụ của bạn, khi bạn gọi Beta();
, vì nó không bị ràng buộc với bất kỳ đối tượng, chúng ta có thể nói rằng các tài liệu tham khảo không có đối tượng cơ sở, sau đó, giá trị this
sẽ đề cập đến đối tượng toàn cầu.
trường hợp khác xảy ra khi bạn gọi một chức năng đó là ràng buộc như một thuộc tính của một đối tượng, ví dụ:
var obj = {
foo: function() { return this === obj;}
};
obj.foo(); // true
Như bạn có thể thấy, các tài liệu tham khảo được gọi obj.bar();
chứa một đối tượng cơ sở, đó là obj
và giá trị this
bên trong hàm được gọi sẽ tham chiếu đến nó.
Lưu ý: reference type là khái niệm trừu tượng, được xác định cho mục đích triển khai ngôn ngữ bạn có thể xem chi tiết trong thông số.
Một trường hợp thứ ba trong đó giá trị this
được thiết lập ngầm là khi bạn sử dụng các nhà điều hành new
, nó sẽ đề cập đến một đối tượng mới được tạo ra mà được thừa hưởng từ nguyên mẫu constructor của nó:
function Foo() {
return this; // `this` is implicitly returned when a function is called
} // with `new`, this line is included only to make it obvious
var foo = new Foo();
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true
+1. Tràn hơn bao giờ hết. –
Cảm ơn bạn @Tim! – CMS