问题描述
|
在Javascript中,污染全局名称空间通常被认为是一件坏事。这就是为什么Coffeescript将所有Javascript包裹在
(function() {}).call(this);
包装器中的原因。
但是,我已经开始为我的Coffeescript代码编写QUnit测试,并且QUnit抱怨它找不到我的函数。
1. Died on test #1: getGoodNamePart is not defined
getGoodNamePart is not defined at Object.<anonymous> (file:///Users/kevin/Documents/docs/code/chrome/tests.js:2:10) at Object.run
我想测试变量而不污染全局名称空间。什么是执行此操作的好方法?
这是我要测试的生成的Javascript:
(function() {
getGoodNamePart = function(str) {
if (str.charat(0) === \'\"\') {
str.replace(/\" <[^>]+>$\"/g,\"\");
str.replace(/\"/g,\"\");
return str;
} else if (str.charat(0) === \'<\') {
str.replace(/<|>/g,\"\");
return str;
} else {
return str;
}
};
}).call(this);
而我的test.js文件是:
test(\'getGoodNamePart()\',function() {
equals(getGoodNamePart(\"\\\"Kev Burke\\\" <kev@inburke.com>\"),\"Kev Burke\",\"\\\"name\\\" <email> works\");
equals(getGoodNamePart(\"\",\"\",\"empty string works\"));
equals(getGoodNamePart(\"kev@inburke.com\",\"kev@inburke.com\",\"raw email works\"));
return equals(getGoodNamePart(\"<kev@inburke.com>\",\"email inside carets -> carets get stripped\"));
});
谢谢,
凯文
解决方法
因此,您说您想测试
getGoodNamePart
而不污染全局名称空间。但是,CoffeeScript自动对每个文件进行模块化(有充分的理由,请参见此处的答案),这意味着跨文件访问功能的唯一方法是将它们附加到某个全局对象。 (我假设我们在这里谈论的是浏览器,而不是诸如Node.js之类的CommonJS环境,在该环境中您将使用ѭ5)。)
这给了您三个选择:
将getGoodNamePart
连接到window
。这是最简单的,因为唯一的更改是将getGoodNamePart
前缀为window.
(或仅是@
),但这当然会最大程度地污染命名空间。
将getGoodNamePart
连接到已经连接到window
或global
的其他物体上。
将测试移至与ѭ4相同的文件内(在JS世界中,这是一种不常见的做法,但值得考虑,因为它可以使全局名称空间保持不变,并使您可以轻松地在代码和测试之间进行切换)。
假设您想使用#2,仅导出getGoodNamePart
之类的函数进行测试。称它们为“测试目标”。在每个带有测试目标的文件的顶部,添加
window.testTargets ?= {}
当你定义ѭ4write时,写
testTargets.getGoodNamePart = getGoodNamePart = (str) ->
...
然后在QUnit测试套件的顶部,编写
{getGoodNamePart} = testTargets
获得功能。
, 我用--bare标志编译了咖啡文件,以进行测试
$ coffee -c -b your_file
这不会模块化已编译的代码