2009-12-02 66 views
0
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中开发,因为它是我们Intranet应用程序的目标浏览器。Javascript + namespacing + FF问题

在IE以上,包括一个空白页上时,输出:

hello Kevin
hello Caoimhin

在FF脚本遇到一个错误:

getMyPublicName is not defined

如果我注释掉有问题的行:

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

FF输出:

hello Caoimhin

所以我知道它可以访问私有函数...

任何人都可以解释为什么这是怎么回事?我需要为了有类似上述一个跨浏览器的解决方案做..

什么我知道我可以写的东西,如:

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

,但宁愿不....

在此先感谢, 凯文

回答

5

你偶然发现了IE使用的JScript语言错误。

getMyPublicName: function getMyPublicName() { 
    ... 
}, 

function getMyPublicName()值这里是已经给予的可选标识符getMyPublicName那是一样的,在它的所有者的属性名的内联函数表达式。 (sayHello忽略了这个标识符。)

什么可选的标识应该就根据ECMAScript标准是使该功能的函数体本身的范围可见的引用,所在的标识符名称getMyPublicName。这可以用于创建一个匿名内联函数(用于递归)。

它实际上确实在IE什么,不正确,是使父范围名getMyPublicName(该utils功能)下的功能可见。因为它在该范围内可见,所以它也可以在sayHello函数的子范围内看到,从而使代码在不应该的时候正常工作。

正如Dustin所建议的那样,您可以使用this.正确获得对getMyPublicName的引用。或者,如果您想要避免在JavaScript中绑定this的问题(例如,因为您要将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, 
     } 
    } 
}(); 
+0

感谢您的详细解释,这里有一些很棒的信息给我。 – Kevin 2009-12-03 04:28:14

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(); 
4

Firefox的行为是一致的,因为对象初始化程序中的函数定义是函数表达式而不是 a 函数声明

ECMA-262,第3版,第13条:

The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.

我建议把这个定义了对象初始化剂:

这样的
+0

感谢您回答这么好 – Kevin 2009-12-03 04:29:39

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