3

在我自己对解释用 JSON 编写的代码的 JavaScript VM的回答中,我指出不能在“私有”函数中访问 JavaScript 闭包的“公共”属性。

该帖子中给出的示例是

function anobject(){
    var privatefunction = function(){
        //publicfunction(); //wrong; you have no access to it
        console.log(this); //refer to the global object, not the object creating
    };
    this.publicfunction = function(){
        console.log(this); //refer to the object creating
    }
}

我认为原因是某些向后兼容性问题privatefunction必须属于全局对象。所以 public 函数只是一个匿名函数,它分配给 的属性this。这解释了为什么调用publicfunction会失败,因为它需要this首先引用。

但是,以下修复仍然无效:

function anobject(){
    var privatefunction = function(){
        //publicfunction(); //wrong; you have no access to it
        console.log(this); //refer to the object creating
    }.bind(this);
    this.publicfunction = function(){
        console.log(this); //refer to the object creating
    }
}

正如我明确指定privatefunction应该与创建的对象绑定一样,调用publicfunction应该可以工作,但不能。我必须执行以下操作:

function anobject(){
    var privatefunction = function(){
        this.publicfunction();
        console.log(this); //refer to the object creating
    }.bind(this);
    this.publicfunction = function(){
        console.log(this); //refer to the object creating
    }
}

另一个解决方法(我使用的方式)如下:

function anobject(){
    var privatefunction = function(){
        publicfunction();
        console.log(this); //refer to the object creating
    };
    var publicfunction = function(){
        console.log(this); //refer to the object creating
    }
    this.publicfunction = publicfunction;
}

现在是问题部分。这种行为背后的原因是什么?this通过在没有明确说明的情况下禁用 access 的属性来试图避免什么?

更新:问题的主要部分是:当解释器在范围链中找不到名称时,为什么不应该查看this属性?

4

2 回答 2

4

这里的问题是引用this是由函数/方法的调用者决定的,例如:

function anobject(){
    // here "this" is the object
    var privatefunction = function(){
        // here "this" is the object **that called privatefunction()**
    };
    this.publicfunction = function(){
        // this method will always be called by the object, so "this" is the object
    }
}

为了实现你想要的,你也可以试试这个:

function anobject(){
    var that = this;
    var privatefunction = function(){
        [do what you like using "that"]
    };
    this.publicfunction = function(){
        [here you can use "this" directly, or "that"]
    }
}

另请参阅 javascript 作用域的工作原理,此处是 JavaScript 中变量的作用域是什么?并在网络上。

于 2012-11-28T12:52:24.920 回答
1

在第二个示例中,publicfunction()作为对象的属性this被删除:

this.publicfunction = function(){
    console.log(this);
}

因此,此函数不能通过其名称直接访问publicfunction(),并且与上下文无关。该函数实际上并不属于任何上下文,而是属于它作为属性的对象

在您的示例中,当privatefunction()调用时publicfunction(),这会引发错误,因为没有函数声明为具有 name的变量publicfunction(),而不是因为this的属性不可访问:

function anobject(){
    var privatefunction = function(){
        //publicfunction(); // You cannot call publicfunction() because there is
                            // no function defined with this name
    }.bind(this);
    this.publicfunction = function(){
        console.log(this);
    }
}

看这个例子,publicfunction()即使在以下范围内也无法访问anobject()

function anobject(){
    this.publicfunction = function() {
        console.log(this);
    }
    // publicfunction(); // Wrong because publicfunction()
                         // was not defined as a variable
}

但是,如果在 的上下文中publicfunction()定义为变量anobject(),则可以通过其名称访问该函数。例如,您可以简单地function publicfunction()在以下闭包中声明anobject()

function anobject(){
    function publicfunction() {
        console.log(this);
    }
    publicfunction(); // You can access publicfunction() here
}

但在这种情况下,publicfunction()在 的执行上下文之外无法访问anobject(),因此可以将其视为“私有”函数:

var a = new anobject();
if(typeof a.publicfunction === 'undefined')
    console.log('Public function is undefined outside of anobject()');

因此,这就是我们使用this关键字声明的原因publicfunction():它使它可以在 的上下文之外访问anobject(),但这样做只将此函数定义为的属性anobject()

因此,访问此函数的唯一方法是调用this.publicfunction()

function anobject(){
    var privatefunction = function(){
        this.publicfunction();
        console.log(this);
    }.bind(this);
    this.publicfunction = function(){
        console.log(this);
   }
}

this有关关键字的更多详细信息: “this”关键字在函数中如何工作?

JavaScript 中的变量与属性:http: //javascriptweblog.wordpress.com/2010/08/09/variables-vs-properties-in-javascript/

于 2012-11-28T13:27:28.063 回答