JavaScript Faux Pas - 让我把全局库放在窗口上?

时间:2015-04-24 11:31:52

标签: javascript requirejs global

我正在使用RequireJS。我非常讨厌定义依赖关系并将其作为回调函数中的变量传递的双变量语法。因此,我正在尝试实现RequireJS中提供的'Sugar'语法。

但是,我只想“导入”Backbone,jQuery,Underscore和Marionette等全局库。 jQuery和Backbone显然将自己分配给Window对象,但是Underscore和Marionette没有。

这是我的main.js文件:

require.config({
  paths: {
    "jquery" : "vendor/jquery.min",
    "underscore": "vendor/underscore-min",
    "backbone" : "vendor/backbone-min",
    "marionette" : "vendor/marionette",
    "app" : "app/app"
  }
});

define(function(require, exports, module) {

    // Make these libraries available globally
    var jquery          = require('jquery');
    window.underscore   = require('underscore');
    var Backbone        = require('backbone');
    window.marionette   = require('marionette');

    // Require and start our own app
    var app             = require('app');
    app.start();
});

这显然阻止了我必须将每个核心库导入/需要到我的应用程序的每个后续模块/组件中。从可能的这个(app.js文件)获取我的代码:

define(function (require, exports, module) {

     var jquery = require('jquery'),
        underscore = require('underscore'),
        Backbone = require('backbone'),
        Marionette = require('marionette'),

        // module specific libs
        mymodule = require('../js/app/module'),
        logger   = require('../js/app/logger');

    return {
        start: function () {
            var testview = new mymodule();
            logger.logme();
        }
    }
});

对此(更好的app.js):

define(function (require, exports, module) {

    var mymodule = require('../js/app/module'),
        logger   = require('../js/app/logger');

    return {
        start: function () {
            var testview = new mymodule();
            logger.logme();
        }
    }
});

更清洁的IMO。

那么想法?批评?这些会一起发挥好吗? (两个人已经自己做了 - 如果他们是应用程序的核心,为什么不为其他两个)。

在我看来,只要我没有开始将每个模块/组件/库都放到全球范围内,我认为这不会是一个问题,但我对那些经验丰富的人感兴趣。

如果我做错了或有更好的方式让我知道!

由于

1 个答案:

答案 0 :(得分:0)

编辑:阅读完评论后,我意识到您的问题有两个组成部分。一个组件纯粹是语法 - 我的原始答案解决了该组件的可能解决方案。但是,如果您的解决方案还包含应用程序设计组件,从而在应用程序级别定义各个模块的依赖关系,那么我的答案就是“不良实践”。应在模块级别(或更低级别)定义依赖关系,以便应用程序的每个元素都可以解耦。这将是编写代码的巨大好处,这些代码是(1)可重用的,(2)可测试的,(3)可重构的。通过在应用程序级别定义依赖关系,您可以强制自己加载整个应用程序,只需访问单个模块,例如,运行测试 - 并禁止重新安排模块或在其他项目中重用相同的模块。如果你这样做,从长远来看......你将度过一段美好时光。

现在,在某种程度上你的问题是语法......

原始答案:我同意require.js语法很难看,使用起来很烦人,也是一个难以调试错误的潜在来源。我自己的方法是实现以下包装功能(原谅coffeescript)。

# Takes dependencies in the form of a hash of arguments with the format
# { path: "name"}
# Assigns each dependency to a wrapper variable (by default "deps"),
# without the need to list each dependency as an argument of the function.
PrettyRequire = (argHash, callback) ->
    deps = new Array()
    args = new Array()

    #loops through the passed argument, sorts into two arrays.
    for propt of argHash
        deps.push(propt)
        args.push(argHash[propt])

    #calls define using the 'dependency' array   
    define(deps, ()->
        deps = new Array()

        # assigns the resulting dependencies to properties of the deps object
        for arg, i in args
            deps[arg] = arguments[i]

        # runs callback, passing in 'deps' object
        return callback(deps)
    )

这段代码是一个简单的重写,它(1)保留范围,(2)美化语法。我只是将函数作为我维护的内部库的一部分包含在内,并在任何项目的开头包含该库。

然后可以使用以下(imho)更漂亮的语法调用Define:

PrettyRequire({
    'backbone': 'Backbone'
    'vendor/marionette': 'Marionette'
    '../js/app/module': 'myModule'
}, (deps)->
    Backbone.Model.extend(...) # for dependencies that assign themselves to global
    deps.myModule(...) # for all dependencies (including globals)
) 

这是我的方法,只要它能回应你的问题。值得注意的是,由于增加的开销,您的应用程序将受到(小)性能影响,但只要您没有调用太多子模块,它就不应该是一个问题,并且我,不值得处理你描述的双重语法是值得的。