Javascript + namespacing + FF问题

Kev*_*vin 0 javascript firefox namespaces

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();
Run Code Online (Sandbox Code Playgroud)

我正在玩javascript命名空间,并遇到了意外的行为.我主要在IE中开发,因为它是我们的Intranet应用程序的目标浏览器.

在上面的IE中,当包含在空白页面上时,输出:

你好凯文
你好Caoimhin

在FF中,脚本遇到错误:

getMyPublicName未定义

如果我注释掉违规行:

//document.writeln("hello " + getMyPublicName() + "<br/>");
Run Code Online (Sandbox Code Playgroud)

FF输出:

你好Caoimhin

所以我知道它可以访问私有功能......

任何人都可以解释为什么会这样吗?我需要做的是为了拥有类似于上面的跨浏览器解决方案..

我知道我可以这样写:

document.writeln("hello " + utils.messages.getMyPublicName() + "<br/>");
Run Code Online (Sandbox Code Playgroud)

但不愿意......

凯文,提前谢谢

bob*_*nce 5

您偶然发现了IE使用的JScript语言中的错误.

getMyPublicName: function getMyPublicName() {
    ...
},
Run Code Online (Sandbox Code Playgroud)

function getMyPublicName()这里的值是一个内联函数表达式,它已被赋予一个可选的标识符getMyPublicName,该标识符与所有者中的属性名称相同.(sayHello省略此标识符.)

根据ECMAScript标准,可选标识符应该做的是在标识符名称下引用函数体本身范围内可见的函数getMyPublicName.这可以用于创建一个引用自身的匿名内联函数(用于递归).

它在IE中实际上做的不正确的是使该函数getMyPublicName在父作用域(utils函数)中的名称下可见.因为它在该范围内可见,所以它对sayHello函数的子范围也是可见的,使得代码在不应该的时候工作.

正如Dustin建议的那样,您可以使用正确this.的参考getMyPublicName.或者,如果您想避免thisJavaScript中的-binding 问题(例如,因为您要将该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,
        }
    }
}();
Run Code Online (Sandbox Code Playgroud)