有人可以解释为什么会出现在Javascript中吗?
var singleton = window.singleton || {};
singleton.methods = (function () {
var _private = function() {
console.log('outer private function');
}
return {
_private: function() {
console.log('inner private');
},
public: function() {
_private();
}
}
})();
singleton.methods.public();
我的直觉让我相信调用.public()
应该记录'内部私有'。它没有。如果我将public()
定义更改为this._private()
,我会得到我期望的结果。为什么呢?
答案 0 :(得分:2)
你有一个范围问题:_private
函数中的public
指的是构造闭包中定义的一个(闭包是由函数调用定义的,你返回的块没有定义一个范围)。
如果要记录返回的对象的_private
方法,请将定义更改为
return {
_private: function() {
console.log('inner private');
},
public: function() {
this._private();
}
}
这是what the MDN says about closures:
简而言之,闭包的父函数中的变量仍然与父级的范围绑定。
要解决_private
功能中的public
,您必须按顺序搜索
public
函数本身中
methods
对象的闭包。该功能在那里找到答案 1 :(得分:0)
我的猜测是,你来自Java这样的语言,当引用不合格的成员名称时,this.
隐含在对象的方法中。在JavaScript中,它不是,而且这是你问题的根源。
JavaScript中唯一的例外是顶级范围 - 浏览器中的window
- 是专门处理的。如果我在顶级声明var foo = "bar"
,则会创建一个名为window
foo
的属性,其值为"bar"
,因此看起来会像您一样期待:
this.foo = "bar";
alert(foo); // shows bar
alert(this.foo); // also shows "bar"
但总的来说,在顶级范围之外,这不是真的。因此,名为public
的函数正在查找名为_private的范围变量,并且名为_private
- this._private
的同一对象的属性不是该范围内的变量或其他任何变量。范围。
答案 2 :(得分:0)
记录inner private
的函数是对象中的属性。仅使用其名称无法访问该属性,您必须指定它在对象中。
在像C#和Java这样的面向对象语言中,方法的范围包含来自对象的标识符,但它不像Javascript中那样工作。它只有函数作用域(和全局作用域),因此您无法在不指定它们所属的对象的情况下访问对象成员。
答案 3 :(得分:0)
你拥有的是一个封闭物。当您在闭包中返回一个函数时,该函数会被暴露,因此“公开”。闭包内的每个函数都保留其真正的私有范围。所以当你调用_private();从公共函数,你实际上是在调用内部函数。 你的public _private()属于构造函数,要求你应该为它应用一个合适的链。像这样:
this._private()