JavaScript中的名称空间:是否需要重写所有变量和函数引用?

JavaScript中的名称空间:是否需要重写所有变量和函数引用?,javascript,Javascript,我正在给一些JavaScript代码命名,我想知道我是否正确地重写了所有函数调用和对全局变量的引用。当前代码如下: var x = 10; function foo() { console.log('foo'); bar(); }, function bar() { console.log('bar', x); } foo(); 我将其改写如下: var namespace = { x : 10, foo: function() { consol

我正在给一些JavaScript代码命名,我想知道我是否正确地重写了所有函数调用和对全局变量的引用。当前代码如下:

var x = 10;
function foo() {
    console.log('foo');
    bar();
  },
function bar() {
  console.log('bar', x);
}  
foo();
我将其改写如下:

var namespace = {  
  x : 10,
  foo: function() {
    console.log('foo');
    // Is this the correct way to call bar?
    this.bar();
  },
  bar: function() {
    // Is this the correct way to refer to x?  
    console.log('bar', this.x);
  }  
};
namespace.foo();

这是否正确,也就是说,我是否需要将所有函数调用重写为EDIT:我的意思是将名称空间变量中的所有变量重写为this.functionname,将所有全局变量重写为this.variablename

否,在某些地方,从命名空间对象外部调用这些函数的代码必须调用namespace.foo、namespace.bar、namespace.varName

实际上,如果您在对象本身的函数中使用namespace.bar,您将获得额外的好处,即您的函数不依赖于上下文。也就是说,下面的代码与您拥有的不兼容

var fun = namespace.foo;
fun(); // This would break, since the this value is going to be the global object

由于上面提到的问题,我通常不喜欢从文字对象使用它。这绝对是一种偏好,我只是想避免这个问题如果你愿意,你可以通过合并闭包来创建一些真正的私有变量和方法。我赞成模块模式

var ns = (function () {  
  var x = 10;
    return {
        foo: function () {
            console.log('foo');
            this.bar();
        },
        bar: function () {
            console.log('bar', x);
        },
        increment: function () {
            x++;   
        }
    }
}());

ns.foo();
ns.increment();
ns.foo();

不,不应重写为this.funcname,而应重写为namespace.funcname。this关键字保留用于引用当前上下文对象或其调用的任何对象,这意味着您将在名称空间代码中使用它来引用名称空间对象

一般来说,很高兴知道您并没有像从更经典的OOP中了解到的那样使用名称空间。JavaScript是一种基于原型的语言,这意味着您没有名称空间——相反,您创建的是一个包含多个属性和方法的对象。如前所述,当您使用对象的方法时,this关键字指的是对象本身。当对象超出其上下文时,您需要对其进行引用


目前,使用对象来包含所有代码作为一种名称空间和类伪装的方法正在逐渐减少,取而代之的是闭包,闭包将公开可用的方法和属性附加到函数上,而函数在JavaScript中是第一类对象,并返回该函数或将其附加到全局对象。您也可以使用函数来包含属性和方法,而不是对象。

我不同意那些对您的问题说不的人。这真的取决于你想在这里完成什么。根据重写的代码,我看不出有什么问题。只要调用namespace.foo,每个函数的执行上下文都应该是namespace。因此,使用这种方法并没有错

存在调用函数foo无法工作的情况:

var foo1 = namespace.foo;
foo1();

尽管foo1与函数namespace.foo相同,但foo1的执行上下文已更改。这将引用窗口,而不是名称空间。

它们不需要重写那么多,因为您可以有多个函数引用—一个私有函数和一个公共函数

var namespace = (function() {
    var ns = {}; // the 'namespace'
    var x = 10;

    var foo = // 'private' reference: bar();
    ns.foo =  // 'public'  reference: ns.bar() -> namespace.bar();
    function foo() { // the name is optional because it's a function expression
        console.log('foo');
        bar();
    }; // don't forget the semicolon

    var bar =
    ns.bar =
    function() {
        console.log('bar', x);
    };

    return ns; // return the 'namespace'
})();

namespace.foo();

var foo = namespace.foo;
foo();
delete namespace.bar;
// namespace.bar(); // Error
foo(); // bar is called

谢谢-关于变量,它们是否也应该声明为namespace.x:10?如果您从namespace对象的外部引用它们,是的。但是使用等号而不是冒号作为赋值运算符。当在对象代码中声明时,只需使用x:10。如果在名称空间对象中引用它们呢?this.x或namespace.x?这取决于它们都是有效的,因为JavaScript不是强类型语言,但它们有各自的用例。如果名称空间是一个在任何时候都没有以任何方式复制或实例化的对象,则可以在代码中使用namespace.x使其引用自身。但是,如果您正在创建对象/函数的实例,则应该使用这个.x,它将引用对象实例。我个人更喜欢在任何情况下使用它,因为它通常比对象的名称短,从而使代码更简洁、更不冗长。我们不希望JavaScript看起来像Java。