coffeescript中的名称空间

coffeescript中的名称空间,coffeescript,Coffeescript,coffeescript中是否有对名称空间的内在支持 适当的名称空间似乎是coffeescript真正能提供帮助的东西,尽管我似乎找不到任何证据表明有人支持这一点。来自wiki上关于名称空间的部分: #代码: # 名称空间=(目标、名称、块)-> [目标、名称、块]=[(如果导出类型不是“未定义”,则导出其他窗口)、参数…]如果arguments.length

coffeescript中是否有对名称空间的内在支持


适当的名称空间似乎是coffeescript真正能提供帮助的东西,尽管我似乎找不到任何证据表明有人支持这一点。

来自wiki上关于名称空间的部分:

#代码:
#
名称空间=(目标、名称、块)->
[目标、名称、块]=[(如果导出类型不是“未定义”,则导出其他窗口)、参数…]如果arguments.length<3
顶部=目标
target=target[item]或={}用于name.split.'中的项
顶住目标
#用法:
#
名称空间“Hello.World”(导出)->
#“exports”是附加命名空间成员的位置
exports.hi=->console.log“hi World!”
名称空间“Say.Hello”,(导出,顶部)->
#'top'是对主命名空间的引用
exports.fn=->top.Hello.World.hi()
Say.Hello.fn()打印“嗨,世界!”

我更喜欢将此模式用于“名称空间”。它实际上不是一个名称空间,而是一个对象树,但它完成了以下任务:

在应用程序启动的某个地方,您可以根据您的环境全局定义名称空间(将
窗口
替换为
导出
全局

window.App =
  Models: {}
  Collections: {}
  Views: {}
然后,当您想要声明类时,您可以这样做:

class App.Models.MyModel
  # The class is namespaced in App.Models
当您想要引用它时:

myModel = new App.Models.MyModel()
如果不喜欢定义名称空间的全局方式,可以在类之前这样做:

window.App.Models ?= {} # Create the "namespace" if Models does not already exist.
class App.Models.MyModel

在类自身的“名称空间”(闭合函数)和全局名称空间中引用该类非常简单的一种方法是立即分配它。例如:

# Define namespace unless it already exists
window.Test or= {}

# Create a class in the namespace and locally
window.Test.MyClass = class MyClass
  constructor: (@a) ->

# Alerts 3
alert new Test.MyClass(1).a + new MyClass(2).a
如您所见,现在您可以在文件中将其称为
MyClass
,但如果您在文件外部需要它,可以将其称为
Test.MyClass
。如果您只想在测试命名空间中使用它,则可以进一步简化:

window.Test or= {}

# Create only in the namespace
class window.Test.MyClass
  constructor: (@a) ->

你一定要去看看咖啡烤面包机:

它附带了一个打包系统,启用该系统后,将使用文件夹的层次结构作为类的命名空间声明(如果需要),然后可以从多个文件扩展类,执行导入和子操作,例如:

#<< another/package/myclass
class SomeClass extends another.package.MyClass
还有一个单独编译文件的调试选项,以简化调试过程和其他有用的功能


希望它能有所帮助。

因为我也在忙着学习构造文件的最佳方法,并将coffeescript与主干和cake结合使用,所以我创建了一个用于保存它作为我自己的参考,也许它也会帮助你处理cake和一些基本的事情。All.js(带有cake编译文件)位于www文件夹中,这样您就可以在浏览器中打开它们,并且所有源文件(蛋糕配置除外)都位于src文件夹中。在本例中,所有.coffee文件都被编译并合并到一个output.js文件中,然后包含在html中


根据StackOverflow上的一些答案,我创建了一个小的util.coffee文件(在src文件夹中),它向代码的其余部分公开“名称空间”。

我强烈建议使用requirejs.org或类似的经过战斗测试的模块加载程序。 特别是当你想异步加载的时候

如果您忽略了这一点,那么使用自己的名称空间/模块方案是非常困难的
简单、简单和天真的方法

以下是我的个人实现:

如何在浏览器中使用:

namespace Foo:SubPackage1:SubPackage2:
  class Bar extends Baz
    #[...]
如何在CommonJS环境中使用:

require './path/to/this/file' # once

namespace Foo:SubPackage1:SubPackage2:
  class Bar extends Baz
    #[...]

请注意,可以编写:

class MyObject.MyClass
    constructor: () ->
        initializeStuff()
    myfunction: () ->
        doStuff()
如果您声明了一个对象/ns MyObject

在这里,我实现了一个jquery ns函数:

(function($) {
    $.namespace = function(namespace, initVal) {
        var nsParts = namespace.split("."),
            nsPart = nsParts.shift(),
            parent = window[nsPart] = window[nsPart] || {},
            myGlobal = parent;
        while(nsPart = nsParts.shift()) {
            parent = parent[nsPart] = parent[nsPart] || {};
        }
        return myGlobal;
    }
})(jQuery);

您有自动关闭的文件,这还不够吗?您必须详细说明“名称空间”的含义这是一个模棱两可的术语。我不会说这是CoffeeScript中流行的模式。人们通常只直接编写
exports.foo=bar
。请注意,您不必在这里使用
window.App.Models
。只需
App.Models?={}
可以。正确。我喜欢引用
窗口。
在我的作业中,为了明确我的意思是做一个全局作业。对我来说,这只是一个编码风格的东西。我喜欢这个选项,它很好,很干净,很适合咖啡脚本语法。+1’我也非常喜欢这个解决方案,但IntelliJ的想法有一个换行符每次之后“:”自动格式化CoffeeScript代码时,该代码会断开文件:(在大多数压缩库下会断开(例如,您的缩小版本将无法工作)。命名空间名称下的类会损坏。这里的一个关键问题是window。没有它,我的编译器会出错。
class MyObject.MyClass
    constructor: () ->
        initializeStuff()
    myfunction: () ->
        doStuff()
(function($) {
    $.namespace = function(namespace, initVal) {
        var nsParts = namespace.split("."),
            nsPart = nsParts.shift(),
            parent = window[nsPart] = window[nsPart] || {},
            myGlobal = parent;
        while(nsPart = nsParts.shift()) {
            parent = parent[nsPart] = parent[nsPart] || {};
        }
        return myGlobal;
    }
})(jQuery);