使用AMD,CommonJS和ES Harmony编写模块化JavaScript代码(AMD VS CJS)

来源:互联网 发布:手机淘宝达人淘在哪里 编辑:程序博客网 时间:2024/06/05 17:07

AMD vs. CommonJS 竞争,但同样有效的标准


本文强调使用AMD要多于CommonJS,但是实际上它们各有用武之地。

AMD更适合浏览器优先开发,适用于一步行为,以及简化向后兼容,但是它并不包含文件I/O的概念。它支持对象,函数,构造器,字符串,JSON以及很多类型的模块,可以直接在浏览器中运行,具有较高的灵活性。

CommonJS这是适于作为服务优先的解决方案,更是和同步行为,项John Hann所推荐的,不存在全局的baggage,并且对未来的服务端开发有更强的适应性。这样说是因为,CJS支持非封装的模块,感觉更像是ES.next/Harmony的规范,对AMD中强制要求的define()在这里不再被强制要求。但是CJS模块仅支持对象作为模块。

虽然不同模块的不同规范可能令人混淆,但是你可能会对混合AMD/CJS和通用AMD/CJS模块感兴趣。

基础AMD混合规范(John Hann)

define( function (require, exports, module){    var shuffler = require('lib/shuffle');    exports.randomize = function( input ){        return shuffler.shuffle(input);    }});

AMD/CommonJS通用模块定义(Variation 2, UMDjs)

/** * exports object based version, if you need to make a * circular dependency or need compatibility with * commonjs-like environments that are not Node. */(function (define) {    //The 'id' is optional, but recommended if this is    //a popular web library that is used mostly in    //non-AMD/Node environments. However, if want    //to make an anonymous module, remove the 'id'    //below, and remove the id use in the define shim.    define('id', function (require, exports) {        //If have dependencies, get them here        var a = require('a');        //Attach properties to exports.        exports.name = value;    });}(typeof define === 'function' && define.amd ? define : function (id, factory) {    if (typeof exports !== 'undefined') {        //commonjs        factory(require, exports);    } else {        //Create a global function. Only works if        //the code does not have dependencies, or        //dependencies fit the call pattern below.        factory(function(value) {            return window[value];        }, (window[id] = {}));    }}));

扩展的UMD插件(我和Thomas Davis)

core.js

// Module/Plugin core// Note: the wrapper code you see around the module is what enables// us to support multiple module formats and specifications by // mapping the arguments defined to what a specific format expects// to be present. Our actual module functionality is defined lower // down, where a named module and exports are demonstrated. ;(function ( name, definition ){  var theModule = definition(),      // this is considered "safe":      hasDefine = typeof define === 'function' && define.amd,      // hasDefine = typeof define === 'function',      hasExports = typeof module !== 'undefined' && module.exports;  if ( hasDefine ){ // AMD Module    define(theModule);  } else if ( hasExports ) { // Node.js Module    module.exports = theModule;  } else { // Assign to common namespaces or simply the global object (window)    (this.jQuery || this.ender || this.$ || this)[name] = theModule;  }})( 'core', function () {    var module = this;    module.plugins = [];    module.highlightColor = "yellow";    module.errorColor = "red";  // define the core module here and return the public API  // this is the highlight method used by the core highlightAll()  // method and all of the plugins highlighting elements different  // colors  module.highlight = function(el,strColor){    // this module uses jQuery, however plain old JavaScript    // or say, Dojo could be just as easily used.    if(this.jQuery){      jQuery(el).css('background', strColor);    }  }  return {      highlightAll:function(){        module.highlight('div', module.highlightColor);      }  };});

myExtension.js

;(function ( name, definition ) {    var theModule = definition(),        hasDefine = typeof define === 'function',        hasExports = typeof module !== 'undefined' && module.exports;    if ( hasDefine ) { // AMD Module        define(theModule);    } else if ( hasExports ) { // Node.js Module        module.exports = theModule;    } else { // Assign to common namespaces or simply the global object (window)        // account for for flat-file/global module extensions        var obj = null;        var namespaces = name.split(".");        var scope = (this.jQuery || this.ender || this.$ || this);        for (var i = 0; i < namespaces.length; i++) {            var packageName = namespaces[i];            if (obj && i == namespaces.length - 1) {                obj[packageName] = theModule;            } else if (typeof scope[packageName] === "undefined") {                scope[packageName] = {};            }            obj = scope[packageName];        }    }})('core.plugin', function () {    // define your module here and return the public API    // this code could be easily adapted with the core to    // allow for methods that overwrite/extend core functionality    // to expand the highlight method to do more if you wished.    return {        setGreen: function ( el ) {            highlight(el, 'green');        },        setRed: function ( el ) {            highlight(el, errorColor);        }    };});

app.js

$(function(){    // the plugin 'core' is exposed under a core namespace in     // this example which we first cache    var core = $.core;    // use then use some of the built-in core functionality to     // highlight all divs in the page yellow    core.highlightAll();    // access the plugins (extensions) loaded into the 'plugin'    // namespace of our core module:    // Set the first div in the page to have a green background.    core.plugin.setGreen("div:first");    // Here we're making use of the core's 'highlight' method    // under the hood from a plugin loaded in after it    // Set the last div to the 'errorColor' property defined in     // our core module/plugin. If you review the code further down    // you'll see how easy it is to consume properties and methods    // between the core and other plugins    core.plugin.setRed('div:last');});
0 0
原创粉丝点击