Vấn đề là bạn đang đi qua một hàm một tham chiếu đến chức năng khác, và do đó các chức năng thông qua là mất phạm vi! Dưới đây là dòng vi phạm:.. đối tượng
Circle.prototype.increaseRadiusBy = function(number) {
this.r = sumWithFunction(this.getRadius, number);
}
Javascript là trong một số cách đơn giản hơn chúng xuất hiện khi bạn thêm một phương thức getRadius
để nguyên mẫu Circle
, bạn không được xác định một phương pháp học như bạn sẽ trong OO cổ điển bạn là đơn giản xác định thuộc tính có tên của nguyên mẫu và gán af unction đến giá trị của tài sản đó. Khi bạn vượt qua this.getRadius
làm đối số cho hàm tĩnh, như sumWithFunction
, ngữ cảnh this
bị mất. Nó thực thi với từ khóa this
được liên kết với window
và do window
không có thuộc tính r
, trình duyệt sẽ phát ra lỗi không xác định.
Nói cách khác, tuyên bố this.getRadius()
đang thực sự nói "thực hiện chức năng giao cho getRadius
tài sản của this
, và thực hiện nó trong bối cảnh của this
. Nếu không gọi hàm một cách rõ ràng thông qua tuyên bố rằng, bối cảnh không được phân định.
một giải pháp chung cho điều này là thêm một đối số dự kiến đến bất kỳ chức năng mà nhận chức năng khác, ví ngữ cảnh.
function sumWithFunction(func, context, number) {
return func.apply(context) + number;
}
function Circle(X, Y, R) {
this.x = X;
this.y = Y;
this.r = R;
}
Circle.prototype.getRadius = function() {
return this.r;
}
Circle.prototype.increaseRadiusBy = function(number) {
this.r = sumWithFunction(this.getRadius, this, number);
}
function addFivetoIt(func, context) {
func.apply(context,[5]);
}
var MyCircle = new Circle(0, 0, 10);
addFivetoIt(MyCircle.increaseRadiusBy, myCircle);
Một giải pháp đơn giản hơn nhưng ít mạnh mẽ hơn là khai báo một hàm nội tuyến có thể truy cập tham chiếu ngữ cảnh trong phần đóng cục bộ.
function sumWithFunction(func, number) {
return func() + number;
}
function Circle(X, Y, R) {
this.x = X;
this.y = Y;
this.r = R;
}
Circle.prototype.getRadius = function() {
return this.r;
}
Circle.prototype.increaseRadiusBy = function(number) {
var me = this;
this.r = sumWithFunction(function() {
return me.getRadius()
}, number);
}
function addFivetoIt(func) {
func(5);
}
var MyCircle = new Circle(0, 0, 10);
addFivetoIt(function(number) {
return MyCircle.increaseRadiusBy(number);
});
Nhưng đến nay giải pháp đơn giản nhất là sử dụng một tính năng mới hơn của ECMAScript, một phương thức chức năng được gọi là bind
. It is explained well here, bao gồm thực tế là nó không được hỗ trợ bởi tất cả các trình duyệt. Đó là lý do tại sao rất nhiều thư viện, như jQuery, Prototype, v.v., có các phương thức tiện ích liên kết chức năng cross-browser như $.proxy
.
function sumWithFunction(func, number) {
return func() + number;
}
function Circle(X, Y, R) {
this.x = X;
this.y = Y;
this.r = R;
}
Circle.prototype.getRadius = function() {
return this.r;
}
Circle.prototype.increaseRadiusBy = function(number) {
this.r = sumWithFunction(this.getRadius.bind(this), number); // or $.proxy(this.getRadius,this)
}
function addFivetoIt(func) {
func(5);
}
var MyCircle = new Circle(0, 0, 10);
addFivetoIt(MyCircle.increaseRadiusBy.bind(MyCircle)); // or $.proxy(MyCircle.increaseRadiusBy,MyCircle)
gạch cũng có một vài công cụ ràng buộc: [ '_.bind'] (http://underscorejs.org/#bind) và [' _.bindAll'] (http://underscorejs.org/ #bindAll). –
Wow, deatailed! Không bao giờ mong đợi rằng khó khăn. cần một chút thời gian để tiêu hóa ... – user1510539
@muistooshort Đúng! Hầu hết mọi thư viện đều có, bao gồm [Ext] (http://docs.sencha.com/ext-js/4-1/#!/api/Ext-method-bind), [MooTools] (http: // mootools. net/docs/core/Types/Function # Chức năng: bind), [YUI] (http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_bind) ... bạn có được ý tưởng. – zetlen