如何传递原型功能?

时间:2012-07-08 22:08:24

标签: javascript prototype

我是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);

2 个答案:

答案 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);