闭包中的Javascript值

Javascript value in closure

本文关键字:Javascript 闭包      更新时间:2023-09-26

我真的无法解释自己为什么创建闭包失败,我在下面的代码中得到了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")();

这与闭包无关。

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

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

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

在我看来,你不是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')返回,在您的示例中,函数将返回到全局对象,因此它将指向thiswindow

函数没有绑定到特定的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方法返回一个新函数,该函数将使用此集合调用bind参数的原始函数。Function.prototype.bind MDN 文档

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

在这样的闭包中,当稍后调用时,"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")();

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

如您所愿

v.action("1")

返回定义为的函数

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

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

如前所述,您可以通过使用call而不是括号来调用函数来决定什么应该是this

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

this在JavaScript中的含义相当混乱。帮助我理解的解释可以在《十分钟内的Javascript》的3.3一节中找到。这(严重的灾难)的含义(尽管整个文档需要十多分钟的时间,但值得一读)。