很多js插件源码都有如下代码:
//兼容CommonJs规范
if (typeof module !== 'undefined' && module.exports) module.exports = MyPlugin;
//兼容AMD/CMD规范
if (typeof define === 'function') define(function() { return MyPlugin; });
这两段代码具体作用是什么呢?
对于提高原生插件的编写能力有没有相关方面的书籍可以看呢?
很多js插件源码都有如下代码:
//兼容CommonJs规范
if (typeof module !== 'undefined' && module.exports) module.exports = MyPlugin;
//兼容AMD/CMD规范
if (typeof define === 'function') define(function() { return MyPlugin; });
这两段代码具体作用是什么呢?
对于提高原生插件的编写能力有没有相关方面的书籍可以看呢?
这些基本都是模块化方案,实际上自己页很容易写出模块化的原理
如webpack
(function(modulesArr) {
var rootModule = {};
function __require__(id) {
if (rootModule[id]) {
return rootModule[id].exports;
}
var currentModule = modulesArr[id];
var module = {
id,
exports: {}
};
currentModule.call(module.exports, module.exports, module, __require__);
currentModule[id] = module;
return module.exports;
}
return __require__(0);
})([
function(exports, module, require) {
var m1 = require(1);
console.log(m1);
},
function(exports, module, require) {
exports.msg = 'Hello World';
var m2 = require(2);
m2();
},
function(exports, module, require) {
module.exports = function() {
var str = 'Hello World';
console.log(str);
return str;
};
}
]);
我自己实现的browser端模块化
(function(global) {
'use strict';
var errMsg = Math.random().toString(32).substr(2);
var rootModule = {};
function ModuleCtor(id) {
if (!this || this.__proto__ !== ModuleCtor.prototype) {
return new ModuleCtor(id);
}
this.id = id;
this.exports = {};
this.loaded = !1;
}
function define(id, fn) {
if (typeof id === 'function') {
fn = id;
id = document.currentScript
? document.currentScript.src
: Math.random()
.toString(32)
.substr(2);
}
if (typeof id !== 'string') {
id = '' + id;
}
var module = ModuleCtor(id);
exec();
function __require__(src) {
if (rootModule[src] && rootModule[src].__proto__ === ModuleCtor.prototype) {
return rootModule[src].exports;
}
loadScript(src, function() {
exec();
});
throw new Error(errMsg);
}
function exec() {
try {
fn.call(module.exports, module.exports, module, __require__);
module.loaded = !0;
rootModule[id] = module;
} catch (err) {
if (err.message !== errMsg) {
throw err;
}
}
}
}
function loadScript(src, callback) {
var script = document.createElement('script');
script.src = src;
script.onload = function() {
callback && callback(src);
};
document.body.appendChild(script);
return script;
}
global.define = define;
})(window);
本质都是js没有模块,所以我们就想到全局暴露一个rootModule对象,每一个键都是一个模块,exports对象是依赖的暴露。
如a.js
module.exports = 'Hello World';
b.js
var chars = require('./a');
process.stdout.write(chars + '\n'); // Hello World
但是我们怎么实现呢,(一)编译:如webpack,(二)暴露一个函数,如requirejs、seajs。
webpack 可以配置 output libraryTarget: 'umd', library: 'globalVarName' 打题主说的这种umd包,兼容浏览器,requirejs,node环境。
另外我还是忍不住吐槽一下seajs的垃圾,一个文件的多个require发请求时没有顺序之分,字符串正则来分析依赖。。。如果jQuery的plugin依赖jQuery,需要对jQueryplugin改一下代码讨个套个客,不能直接想requirejs直接在config中声明依赖。垃圾。当然我自己写的模块加载更垃圾,连依赖都不分析。多try几次必然成功。
10 回答11.1k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答5.1k 阅读✓ 已解决
3 回答1.9k 阅读✓ 已解决
4 回答2.5k 阅读✓ 已解决
都是模块化方案。
amd 对应 requireJs
cmd 对应 seaJs
commonJs 对应 nodeJs
之所以都想兼容过去,是因为很多js文件可以兼容运行在浏览器和node环境,为了重复利用,加上你列出的通用代码,是最合适不过的,比如一个字符串处理
trim
,那么就可以在node和browser同时使用。不加模块化代码的话,就可能得写3份重复的js了。