是否可以将命名空间(模块)的一部分“导入”当前范围?

时间:2013-06-29 16:11:52

标签: javascript namespaces

我有一个名为functionalUtilities的模块,它包含许多实用功能。缩写版本看起来像这样:

MYAPP.functionalUtilities = (function() {
function map(func, array) {
  var len = array.length;
  var result = new Array(len);
  for (var i = 0; i < len; i++)
    result[i] = func(array[i]);
  return result;
}
return {
    map:map,
};
})();

然后我有第二个包含核心代码的模块:

MYAPP.main = (function() {

//Dependencies
var f = MYAPP.functiionalUtilities;

//Do stuff using dependencies
f.map(...)

})()

每次我想使用f.map时,都要记得输入map,这似乎很麻烦,很烦人。当然,在依赖项中,我可以通过输入每个functionalUtilities:

var map = f.map,
forEach = f.forEach,

但我想知道是否有更好的方法可以做到这一点?我读过很多关于命名空间的文章都提到了别名,但是没有提出一种方法可以将对象的所有内容导入到范围中。

非常感谢您的帮助,

罗宾

[edit]为了澄清,我想在map中使用我的功能实用程序(MYAPP.main等),而不必每次都使用f.

进行前言

这可以通过遍历MYAPP.functionalUtilities中的每个函数并分配到MYAPP.main中的本地范围变量来实现。但是,这需要的代码量并不能证明其好处,而且这不是一般解决方案。

2 个答案:

答案 0 :(得分:1)

正如我在评论中所说的那样。没有真正的方法可以自动定义对象属性中的局部变量。我唯一想到的就是使用eval:

for (var i in MYAPP.functiionalUtilities) {
    eval("var " + i + " = MYAPP.functiionalUtilities[i];");
}

但是我不会使用这种方法,因为你可以将带有字符串的对象属性作为这样的键:

var obj = {
    "my prop": 1
};

“my prop”可能是对象属性的有效密钥,但它不是有效的标识符。因此,我建议您使用f.prop;

手动编写var prop = f.prop或手动定义本地变量

修改

正如Felix Kling在评论部分中提到的,实际上有另一种方法可以实现这一点,使用with语句,除了它已被删除之外,我并不太了解。

答案 1 :(得分:1)

这是一个迟到的答案 - 我想补充一下basilikum的答案。

1)with关键字在这里很有用!

with(MYAPP.functiionalUtilities) {

    map(console.log, [ 'this', 'sorta', 'works', 'quite', 'nicely!' ]);

    // Directly reference any properties within MYAPP.functiionalUtilities here!!

};

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with

with关键字在某些方面适用于这种情况。当然,应该注意的是,mozilla开发人员链接不鼓励使用with,并且在严格模式下也禁止with。另一个问题是with语句导致其参数成为范围链的头部,这意味着将始终首先检查with块中所有语句的所有标识符。这可能会影响性能。

2)对basilikum答案的改进

虽然函数调用无法将项添加到其父框架的范围,但是每次希望将项列表添加到命名空间时,都有一种方法可以避免输入for循环。

// First, define a multi-use function we can use each time
// This function returns a string that can be eval'd to import all properties.
var import = function(module) {
    var statements = [];
    for (var k in module) statements.push('var ' + i + ' = module["' + i + '"]');
    return statements.join(';');
};

// Now, each time a module needs to be imported, just eval the result of import
eval(import(MYAPP.functiionalUtilities));
map(console.log, [ 'this', 'works!' ]);

这里的想法是用eval(import(MYAPP.functiionalUtilities));替换编写for循环的需要。

像basilikum所说,这里的危险是模块属性需要是有效的标识符名称。