我是javascript的新手,我需要一些帮助。 我试图按功能求和半径,但得到一个未定义的错误:(
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, number);
}
function addFivetoIt(func) {
func(5);
}
var MyCircle = new Circle(0, 0, 10);
addFivetoIt(MyCircle.increaseRadiusBy);
答案 0 :(得分:22)
问题是你传递的函数是对另一个函数的引用,因此传递的函数正在失去范围!这是违规行:
Circle.prototype.increaseRadiusBy = function(number) {
this.r = sumWithFunction(this.getRadius, number);
}
JavaScript对象在某些方面比它们看起来更简单。当您将getRadius
方法添加到Circle
原型时,您没有像在经典OO中那样定义类方法。您只是定义原型的命名属性,并将函数分配给该属性的值。将this.getRadius
作为参数传递给静态函数(如sumWithFunction
)时,this
的上下文将丢失。它使用绑定到this
的{{1}}关键字执行,并且由于window
没有window
属性,浏览器会抛出一个未定义的错误。
换句话说,语句r
实际上是在说“执行分配给this.getRadius()
getRadius
属性的函数,并在上下文中执行< / {> this
。如果不通过该语句显式调用该函数,则不会分配上下文。
一个常见的解决方案是为任何接收另一个函数的函数添加一个期望参数,用于上下文。
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);
但到目前为止,最简单的解决方案是使用ECMAScript的一个新功能,一种名为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);
});
的函数方法。 It is explained well here,包括所有浏览器都不支持的事实。这就是为什么很多库,比如jQuery,Prototype等,都有跨浏览器功能绑定实用程序方法,如$.proxy
。
bind
答案 1 :(得分:0)
默认情况下使用this
in JavaScript is that it contains the object the function was a property of when it was called时比较棘手。因此,当您将MyCircle.increaseRadiusBy
作为参数传递时,然后将其称为func()
,因此该函数不是任何对象的属性。设置this
的最简单方法是使用call()
函数:
function addFivetoIt(func, context) {
// The first parameter to `call()` is the value of `this` in the function
func.call(context, 5);
}
var MyCircle = new Circle(0, 0, 10);
addFivetoIt(MyCircle.increaseRadiusBy, MyCircle);
下面的方法也可以将func
设置为属性,然后再调用它。在实践中,您永远不会这样做,因为它为context
添加了不必要的属性,但这是一个很好的教学示例,展示了this
的工作原理。
function addFivetoIt(func, context) {
context.func = func;
context.func(5);
}
var MyCircle = new Circle(0, 0, 10);
addFivetoIt(MyCircle.increaseRadiusBy, MyCircle);