的問題是,你傳遞一個函數到另一個函數的引用,因此,傳遞的功能正在失去範圍!這裏是出錯的行:。
Circle.prototype.increaseRadiusBy = function(number) {
this.r = sumWithFunction(this.getRadius, number);
}
JavaScript對象是一些比他們似乎更簡單的方法。當你添加getRadius
方法將Circle
原型,你沒有定義一個類的方法,就像您在古典OO你是根本定義原型的命名屬性並分配af接受該財產的價值。當您將this.getRadius
作爲參數傳遞給靜態函數時,如sumWithFunction
,this
的上下文丟失。它執行this
關鍵字綁定到window
,並且因爲window
沒有r
屬性,瀏覽器會引發未定義的錯誤。
換句話說,聲明this.getRadius()
實際上是說:「執行分配給的this
的getRadius
屬性的功能,並在背景的this
。執行它沒有通過聲明,呼籲該功能明確,上下文不被分配。
到一個常見的解決方案是預期的參數添加到接收另一個功能,用於上下文的任何功能。
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);
更簡單但不太穩健的解決方案是聲明一個內聯函數,該函數可以訪問本地閉包中的上下文引用。
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);
});
但是,到目前爲止最簡單的解決方案是使用ECMAScript中的新功能,函數方法中調用bind
。 It is explained well here,包括它不被所有瀏覽器支持的事實。這就是爲什麼很多庫(如jQuery,Prototype等)都具有跨瀏覽器功能綁定實用程序方法(如$.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)
下劃線也有幾個結合工具:['_.bind'](http://underscorejs.org/#bind)和['_.bindAll'](http://underscorejs.org/ #bindAll)。 – 2012-07-08 22:29:07
哇!謝謝!從來沒有料到過這麼難。需要一些時間來消化... – user1510539 2012-07-08 22:35:51
@ muistooshort真的!幾乎每個圖書館都有,包括[Ext](http://docs.sencha.com/ext-js/4-1/#!/api/Ext-method-bind),[MooTools](http:// mootools。 net/docs/core/Types/Function#Function:bind),[YUI](http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_bind)...你明白了。 – zetlen 2012-07-08 22:39:30