为啥将 javascript 命名空间作为一个函数?

Posted

技术标签:

【中文标题】为啥将 javascript 命名空间作为一个函数?【英文标题】:Why base a javascript namespace as a function?为什么将 javascript 命名空间作为一个函数? 【发布时间】:2016-02-14 03:00:32 【问题描述】:

我正在阅读一个必须保持匿名的库的源代码,我看到它使用一个空函数来设置命名空间。它似乎类似于对象字面量表示法 (OLN),只是基是一个函数。

这是一个声明示例。

/**
 * Base namespace for FOO library
 * @name FOO
 * @namespace
 */
function FOO()

FOO.bar = 'bar const..';
FOO.fooFunc = function ()  /* code */ ;
FOO.Bar = function ()  /* some constructor */ ;
FOO.Bar.prototype.baz = function ()  /* A prototype method on FOO.Bar */ ;
...

如您所见,FOO 命名空间是一个空函数。将命名空间声明为空函数有什么意义吗?这是对 OLN 模式的滥用吗?看起来这可能是工厂模式的开始。命名空间上没有原型方法(例如FOO.prototype.bar = ...)。调用FOO() 显然什么也没做。有人认识这种模式吗?

【问题讨论】:

【参考方案1】:

命名函数是hoisted - 有效地移动到其封闭范围的顶部。使用命名函数可以允许在声明命名空间之前进行赋值:

FOO.bar = "bar";
function FOO() 
console.log(FOO.bar); // bar

与对象字面量(或非命名函数)相比:

FOO.bar = "bar";
var FOO = ;
console.log(FOO.bar); // undefined

不太可能有人计划将成员分配到这样的命名空间,但它可能会发生。

我能想到的唯一其他优点是函数可以有一个固有的名称,这可能对调试有用。

例如,如果命名空间成员有 namespace 属性(他们可能没有):

function FOO()
FOO.bar =  namespace: FOO ;
console.log(FOO.bar.namespace); // function FOO()

相比:

var FOO = ;
FOO.bar =  namespace: FOO ;
console.log(FOO.bar.namespace); // Object bar: Object

纯猜测:某些命名空间也可能使用这样的函数进行初始化。这可能是一个不需要任何初始化但选择使用函数来保持一致性的命名空间示例。

【讨论】:

这两点都很好。虽然,我没有看到图书馆利用提升。 我想它会保存FOO || (FOO = function() ) 类型检查模块是否以未知顺序连接到同一范围内。【参考方案2】:

我通常认为这是通过以下方式完成的:

var FOO = FOO || ;

这样全局不会被覆盖。

为什么要声明一个空函数?

这样作者就可以向 FOO 添加方法。这只是一种方法,因为在 javascript 中,包括函数在内的大多数东西都是对象。

请查看此内容以获得更好的解释:How is almost everything in Javascript an object?

【讨论】:

这也是我通常看到的方式。当然,函数是一个对象,但我想知道将命名空间声明为函数是否有任何好处。

以上是关于为啥将 javascript 命名空间作为一个函数?的主要内容,如果未能解决你的问题,请参考以下文章

使用 RequireJS 的 Javascript 命名空间,为啥?

为啥要将类型放在未命名的命名空间中?

为啥 ANSI C 没有命名空间?

为啥当 javascript 命名空间我们说 var myName = myName || [复制]

javascript-单例模式

javascript“命名空间”的费曼输出[原创]