Javascript + namespacing + FF问题

时间:2009-12-02 23:12:03

标签: 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();

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

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

  凯文,你好   你好Caoimhin

在FF中,脚本遇到错误:

  

未定义getMyPublicName

如果我注意到违规行:

//document.writeln("hello " + getMyPublicName() + "<br/>");

FF输出:

  你好Caoimhin

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

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

我知道我可以这样写:

document.writeln("hello " + utils.messages.getMyPublicName() + "<br/>");

但不愿意......

提前致谢, 凯文

4 个答案:

答案 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;
}();