【问题标题】:How to span javascript namespace across multiple files?如何跨多个文件跨越javascript命名空间?
【发布时间】:2012-04-28 19:43:20
【问题描述】:

我已经永远忽略了 javascript。几年前我开始使用 jQuery,这样我就能过得去。但随着我开始更多地做 TDD,我昨天决定真正深入研究 javascript(之后可能还有 coffeescript)。

在我的 ASP.NET Web 窗体应用程序中,我有很多页面,而目前这些页面中的大多数都没有大量的 javascript。我正在改变这一点。我正在使用 Jasmine 和 Chutzpah 来创建我的测试。

我的测试按预期通过和失败。但是后来我想创建一个命名空间,这样我就不会践踏全球空间了。

阅读本文后: http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/

我决定尝试使用本文的自执行匿名函数:第 2 部分(公共和私有)部分中的模式。它似乎具有最大的灵活性,并且似乎很好地封装了事物。

我有一个名为 /Scripts 的文件夹。在该文件夹下是我使用的一些框架,例如 jQuery、jasmine、(twitter) bootstrap 和 modernizr。我还有一个名为 /Site 的子文件夹,我将我的站点代码放在基于页面的多个文件中。 (product.js、billing.js 等)

在 /Scripts/Site 下,我向 /Tests(或 Specs)添加了一个子文件夹,其中包含文件(product_test.js、billing_tests.js 等)。

没有命名空间一切都很好。我有一个使用 padLeft 辅助函数创建的实用程序.js 文件。然后我在另一个 .js 文件中使用了该全局 padLeft。我的测试都成功了,我很高兴。然后我决定找出命名空间并将我的 Scripts/Site/utility.js 更改为如下所示:

(function (myns, $, undefined) {
    //private property
    var isSomething = true;

    //public property
    myns.something = "something";

    //public method
    myns.padLeft = function (str, len, pad) {
        str = Array(len + 1 - str.length).join(pad) + str;

        return str;
    };


    //check to see if myns exists in global space
    //if not, assign it a new Object Literal
}(window.myns= window.myns|| {}, jQuery ));

然后在我的 Scripts/Site/Tests/utility_test.js 我有

/// <reference path="../utility.js" />

describe("Namespace myns with public property something", function () {
    it("Should Equal 'something'", function () {
        expect(myns.something).toEqual('something');
    });
});

通过这个极其简单的测试,我期待 myns.something 以字符串值“something”返回。

它没有。它回来了未定义

那么,如何跨多个文件使用 javascript 命名空间?

很抱歉介绍得太长,但我认为这可能有助于解释我这样做的原因。为什么。我也提出了所有这些,因为我乐于听到有关此设置如何完全错误或部分错误或其他原因的想法。

感谢您抽出宝贵时间阅读此问题。

更新:已解决 感谢大家的帮助。最大的帮助来自评论者@T.J.克劳德。我不知道 jsbin 工具的存在,在确信我将上面的代码放入工具中并且结果正确之后,我知道我的环境中必须有一些东西。

已接受答案中的链接也对我有很大帮助。在看到语法和逻辑是一致的并且可以正常工作后,我只需要确定我的设置有什么问题。我很尴尬地说是我传入了 jQuery,但是在我试图让它工作的测试工具中,我实际上并没有使用 jQuery。这意味着模块实际上并没有被加载 - 所以 myns 从未设置。

谢谢大家。希望这可能对将来的某人有所帮助。如果您使用上述方法,请确保包含 jQuery 对象。另一个选项是不传入 jQuery 并从参数列表中删除 $。

【问题讨论】:

  • 这是一篇关于跨文件实现模块模式的非常好的文章(您在这里使用的是什么):adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
  • 如果utility.jsutility_test.js 都包括在内,那么您所展示的内容应该可以正常工作,并且按此顺序排列。示例:jsbin.com/idofog
  • 感谢您的长篇介绍,它帮助我们弄清楚您想要什么:-)
  • @T.J.Crowder 谢谢。该垃圾箱有效,但我不明白为什么它在我的环境中有所不同。我不知道jsbin,所以也谢谢你!我将在那个沙盒中尝试一些事情。

标签: javascript unit-testing javascript-namespaces


【解决方案1】:

尝试将您的命名空间声明放在函数调用之外:

myns = window.myns || {};
(function(myns, $, undefined) {
    ...
}(myns, jQuery));

您现有的语法似乎完全有效,但打破这一行可能有助于找出您的变量范围出了什么问题。

【讨论】:

  • 谢谢,我试过了,结果一样。看来我还有其他事情搞砸了。深入研究...
【解决方案2】:

Javascript 没有命名空间,我猜你在变量作用域方面遇到了麻烦,这与其他语言类似,你所说的是对象。你可以使用

window.myns.something

第一个函数已经将你的对象添加到窗口对象中,并且窗口对象可以从任何地方访问。

【讨论】:

  • 使用这样的嵌套属性是在 Javascript 中模拟命名空间的常用方法。
  • 我知道,但正如你所说,它是“模拟”命名空间。命名空间有很大的不同,例如在 .NET 中,但它类似于 .NET 中的对象(除了在运行时更改接口)
  • @PhilippMehrwald 谢谢。我应该更清楚地说明“模拟名称空间”。随着我试图避免使用window.myns.something的模式。即使将其更改为我的测试文件中的那个也失败了。所以我一定有其他问题。谢谢!
  • myns 最初定义在哪里?
  • @PhilippMehrwald 目前在第一个代码块底部的 Script\utilities.js 中定义:window.myns= window.myns|| {},
猜你喜欢
  • 2011-04-01
  • 2018-05-15
  • 1970-01-01
  • 2014-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多