我想在模块内使用datepickk.js:即使以为该插件支持AMD,也无法在RequireJS中加载它:
http://jsfiddle.net/numediaweb/5xbqqr0j/13/

// Config Object
requirejs.config({
    // Local Directory
    baseUrl: "/js",
    // Script Locations
    paths: {
        // Common Libraries
        "jquery": "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min",
        "datepickk": "//crsten.github.io/datepickk/dist/datepickk.min"
    }
});

// Check Dependencies
requirejs(['jquery', 'datepickk'], function ($, Datepickk) {
    var loadedMods = require.s.contexts._.defined;
    console.log(loadedMods);
    $('#message').text('Loaded modules => '+JSON.stringify(loadedMods));
    return {};
});


如果您检查控制台,将会看到定义了jquery,未定义模块。

知道为什么会这样吗?

我尝试了加载此模块的另一种方式:

require.config({
    paths: {
        'Datepickk': '//crsten.github.io/datepickk/dist/datepickk.min'
    },


但是然后我得到这个错误:

datepickk.js:1146 Uncaught TypeError: Cannot freeze
    at Function.freeze (<anonymous>)
    at Datepickk (datepickk.js:1146)
    at Object.execCb (require.js:1693)
    at Module.check (require.js:881)
    at Module.enable (require.js:1173)
    at Module.init (require.js:786)
    at callGetModule (require.js:1200)
    at Object.completeLoad (require.js:1587)
    at HTMLScriptElement.onScriptLoad (require.js:1714)

最佳答案

编写datepickk.js的AMD代码的人都需要阅读有关如何编写AMD模块的信息。有两个问题:


模块名称被硬编码为Datepickk,因为define调用是define('Datepickk', Datepickk)。第一个参数对名称进行硬编码。这确实是一件坏事,因为RequireJS文档很清楚,开发人员不应对名称进行硬编码,而应让优化程序根据需要添加名称,但是这里没有人注意。

这说明了为什么您的第二个配置(在Datepickk中带有paths的配置)有效,而第一个配置却无效的原因。您必须在Datepickk配置中将其称为paths。如果您希望自己的代码将其引用为datepickk,则除了map外,还可以使用paths配置:

map: {
  "*": {
    datepickk: "Datepickk"
  }
}

是的,即使您解决了上述问题,您仍然会遇到遇到的错误。查看Datepickk的文档,我发现您将其与do new Datepickk(...)一起使用。如果执行此操作,则要冻结的对象应该是构造函数执行时由JavaScript虚拟机分配给this的新对象。如果查看使Datepickk可用于其他代码的代码,则会看到以下内容:

if ( typeof define === 'function' && define.amd ) define('Datepickk', Datepickk);
else if ( typeof exports === 'object' ) module.exports = Datepickk;
else window.Datepickk = Datepickk;


第二和第三分支将Datepickk构造函数导出到世界。没关系。但是,第一个分支对您很重要,它调用define并将Datepickk用作模块工厂。当RequireJS执行define调用时,它将立即调用Datepickk来构建模块。在这种情况下,this未被设置为任何特定值,因此它被设置为当前的Window实例(JavaScript虚拟机执行此操作),并且Object.freeze失败。 define调用应为:

define(function () {
    return Datepickk;
});


(我也删除了硬编码的模块名称。)这将构建一个模块,该模块具有功能Datepickk

10-06 05:29