为什么将 javascript 命名空间作为函数?
Why base a javascript namespace as a function?
我正在阅读一个必须保持匿名的库的源代码,我看到它使用一个空函数来设置命名空间。它看起来类似于对象文字表示法 (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()
显然什么都不做。有人认识这个图案吗?
我通常通过以下方式看到此操作:
var FOO = FOO || {};
这样全局就不会被覆盖。
为什么声明一个空函数?
这样作者就可以向 FOO 添加方法。这只是一种实现方式,因为在 JavaScript 中,包括函数在内的大部分内容都是对象。
请查看此内容以获得更好的解释:How is almost everything in Javascript an object?
命名函数 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}
纯粹的推测:也有可能某些名称空间可以使用这样的函数进行初始化。这可能是一个命名空间的例子,它不需要任何初始化,但选择使用一个函数来保持一致性。
我正在阅读一个必须保持匿名的库的源代码,我看到它使用一个空函数来设置命名空间。它看起来类似于对象文字表示法 (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()
显然什么都不做。有人认识这个图案吗?
我通常通过以下方式看到此操作:
var FOO = FOO || {};
这样全局就不会被覆盖。
为什么声明一个空函数?
这样作者就可以向 FOO 添加方法。这只是一种实现方式,因为在 JavaScript 中,包括函数在内的大部分内容都是对象。
请查看此内容以获得更好的解释:How is almost everything in Javascript an object?
命名函数 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}
纯粹的推测:也有可能某些名称空间可以使用这样的函数进行初始化。这可能是一个命名空间的例子,它不需要任何初始化,但选择使用一个函数来保持一致性。