1

我真的无法解释为什么我无法创建一个闭包,我得到undefined了下面的代码:

function A() {
 this.p1=1;
 this.p2=2;
 this.f1=function(){
    alert(this.p1);
 }
 this.f2=function(){
    alert(this.p2);
    }
 this.action=function(param){
    if (param=='1')
        return this.f1;//by case
    else if (param=='2')
        return this.f2;
    };
}

var v=new A();
v.action("1")();
4

6 回答 6

4

这与闭包无关。

您正在从该方法返回一个函数引用,当您调用它时,您希望它作为对象中的方法执行,但它是作为具有全局范围作为上下文的函数执行的。

使用call方法在对象的上下文中调用函数:

v.action("1").call(v);
于 2012-09-01T22:31:02.203 回答
1

函数没有绑定到特定的 this,也就是说:

(function() { console.log(this) })(); // Window

您可以使用 call 方法,或者(更好)使用 .bind 方法(确保为旧浏览器使用 polyfill):

function A() {
 this.p1 = 1;
 this.p2 = 2;
}
A.prototype.f1 = function() {alert(this.p1)};
A.prototype.f2 = function() {alert(this.p2)};
A.prototype.action = function(param) {
  if ('1' == param) {
    return this.f1.bind(this);
  } else if (param == '2') {
    return this.f2.bind(this);
  }
};

var v = new A();
v.action("1")(); // 1

bind 方法返回一个新函数,该函数调用原始函数,并将 this 设置为 bind 的参数。MDN 上的 Function.prototype.bind 文档

v.action("1")大致相同action.call(v, "1")

于 2012-09-01T22:36:36.410 回答
1

在我看来,您不能 100% 确定闭包是什么……从您的代码开始:

function A()
{
    this.p1=1;//public
    var p2=2;//private
    this.f1=function()
    {
        alert(this.p1);
    };
    this.f2=function()
    {
        alert(p2);
    };

在这里,我定义p2了一个变量,在构造函数的范围内是本地的,但是公共方法f2 可以访问它的值,甚至可以改变它。这是一个闭包:代码/数据包含在它自己的特定范围内。您正在使用以下代码做什么:

    this.action=function(param)
    {
        if (param=='1')
        {
            return this.f1;
        }
        return this.f2;
    };
}
var v=new A();
v.action("1")();

与闭包几乎没有关系,您正在返回对函数的引用(在这种特定情况下恰好是对象方法)。为什么,那么这不是point它来自的对象吗?简单的:

var foo = {name:'someObject'};
foo.retVal = v.action('1');//returns function
//much later:
foo.retVal();

您是否仍然希望this指向v?调试起来不是很糟糕吗?在调用函数(方法与否)时,this将是调用函数的上下文对象的指针。一旦v.action('1')返回,在您的示例中,该函数将返回到全局对象,因此 this 将指向thiswindow

于 2012-09-01T22:40:08.790 回答
0

如你所愿

v.action("1")

返回定义为的函数

function(){
    alert(this.p1);
}

您也可以通过添加一对括号来调用它,就像您所做的那样。但是this,该函数中的 将绑定到全局对象(在浏览器中是window)。并且window.p1undefined。这就是你得到的输出。

如前所述,您可以通过使用而不是方括号来决定this函数中应该包含的内容:call

v.action("1").call(v);

thisJavaScript 中的含义非常令人困惑。帮助我理解的解释可以在第3.3节中找到Javascript 在十分钟内的这个(令人震惊的灾难)的含义(尽管整个文档需要十多分钟,但值得一读)。

于 2012-09-01T22:56:32.260 回答
0

在这样的闭包内部,“this”实际上是指稍后调用的 Window。为了避免这种情况,您需要将“this”分配给另一个变量,例如“that”:

function A() {
var that = this;
 that.p1=1;
 that.p2=2;
 that.f1=function(){
    alert(that.p1);
 }
 that.f2=function(){
    alert(that.p2);
    }
 that.action=function(param){
    if (param=='1')
        return that.f1;//by case
    else if (param=='2')
        return that.f2;
    };
}

var v=new A();
v.action("1")();
于 2012-09-01T22:34:12.697 回答
0

在您的嵌套函数内部this还有另一个含义。尝试使用变量在内部传递引用,请参阅jsfiddle

于 2012-09-01T22:34:28.187 回答