var utils = function() {
function getMyPrivateName() {
return "Caoimhin";
}
return {
messages: {
getMyPublicName: function getMyPublicName() {
return "Kevin";
},
sayHello: function() {
document.writeln("hello " + getMyPublicName() + "<br/>");
document.writeln("hello " + getMyPrivateName() + "<br/>");
}
}
};
} ();
utils.messages.sayHello();
我正在使用javascript命名空间并遇到意外行为。我主要在IE中开发,因为它是我们内部网应用程序的目标浏览器。
在上面的IE中,当包含在空白页面上时,输出:
凯文,你好 你好Caoimhin
在FF中,脚本遇到错误:
未定义getMyPublicName
如果我注意到违规行:
//document.writeln("hello " + getMyPublicName() + "<br/>");
FF输出:
你好Caoimhin
所以我知道它可以访问私人功能...
任何人都可以解释为什么会这样吗?我需要做的是为了拥有类似于上面的跨浏览器解决方案..
我知道我可以这样写:
document.writeln("hello " + utils.messages.getMyPublicName() + "<br/>");
但不愿意......
提前致谢, 凯文
答案 0 :(得分:5)
您偶然发现了IE使用的JScript语言中的错误。
getMyPublicName: function getMyPublicName() {
...
},
这里的function getMyPublicName()
值是一个内联函数表达式,它已被赋予一个可选的标识符getMyPublicName
,该标识符与所有者中的属性名称相同。 (sayHello
省略了此标识符。)
可选标识符应根据ECMAScript标准执行的操作是在标识符名称getMyPublicName
下引用函数体本身范围内可见的函数。这可以用于创建一个引用自身的匿名内联函数(用于递归)。
实际在IE中做错误的是,在父作用域(getMyPublicName
函数)中的名称utils
下显示该函数。因为它在该范围内可见,所以sayHello
函数的子范围也变得可见,使得代码在不应该的时候工作。
根据Dustin的建议,您可以使用this.
正确获取对getMyPublicName
的引用。或者,如果你想避免this
- 在JavaScript中绑定的问题(例如,因为你要将sayHello
函数作为委托传递给超时或事件),你可能更愿意放父范围内的公共函数也是:
var utils = function() {
function getMyPrivateName() {
return "Caoimhin";
}
function getMyPublicName() {
return "Kevin";
}
function sayHello() {
document.writeln("hello " + getMyPublicName() + "<br/>");
document.writeln("hello " + getMyPrivateName() + "<br/>");
}
return {
messages: {
getMyPublicName: getMyPublicName,
sayHello: sayHello,
}
}
}();
答案 1 :(得分:4)
Firefox的行为符合要求,因为对象初始化程序中的函数定义是函数表达式而不 函数声明。
ECMA-262,第3版,第13节:
FunctionExpression中的标识符 可以从里面引用 FunctionExpression的FunctionBody来 允许函数调用自身 递归。但是,不像一个 FunctionDeclaration,标识符 一个FunctionExpression不能 引用并且不影响 封闭范围 FunctionExpression。
我建议将定义移出对象初始化器:
var utils = (function() {
function getMyPrivateName() {
return "Caoimhin";
}
function getMyPublicName() {
return "Kevin";
}
return {
messages: {
getMyPublicName: getMyPublicName,
sayHello: function() {
document.writeln("hello " + getMyPublicName() + "<br/>");
document.writeln("hello " + getMyPrivateName() + "<br/>");
}
}
};
})();
utils.messages.sayHello();
答案 2 :(得分:2)
这是范围问题:
var utils = function() {
function getMyPrivateName() {
return "Caoimhin";
}
return {
messages: {
getMyPublicName: function() {
return "Kevin";
},
sayHello: function() {
document.writeln("hello " + this.getMyPublicName() + "<br/>");
document.writeln("hello " + getMyPrivateName() + "<br/>");
}
}
};
} ();
utils.messages.sayHello();
答案 3 :(得分:0)
这样做的一种方法是:
var utils = function() {
var getMyPrivateName = function () {
return "Caoimhin";
};
var self = {
getMyPublicName: function () {
return "Kevin";
},
sayHello: function() {
document.writeln("hello " + getMyPublicName() + "<br/>");
document.writeln("hello " + self.getMyPrivateName() + "<br/>");
};
return self;
}();