写一个适应所有环境的js模块

说下背景:

在ES6以前,JS语言没有模块化,如何让JS不止运行在浏览器,且能更有效的管理代码,

于是应运而生CommonJS这种规范,定义了三个全局变量:

require,exports,module

require 用于引入一个模块

exports 对外暴露模块的接口,可以是任何类型

module 是这个模块本身的对象

用require引入时获取的是这个模块对外暴露的接口(exports)

Node.js 使用了CommonJS规范:

在浏览器端,不像Node.js内部支持CommonJS,如何进行模块化,

于是出现了 CMD 与 AMD 两种方式,其主要代表是 seajs 和 requirejs,

他们都定义了一个全局函数 define 来创建一个模块:

可以看出CMD完好的保留了CommonJS的风格,

而AMD用了一种更简洁的依赖注入和函数返回的方式实现模块化。

两者除风格不同外最大区别在于加载依赖模块的方式,

CMD是懒加载,在require时才会加载依赖,

而AMD是预加载,在定义模块时就提前加载好所有依赖。

各有千秋,各有适合的场景,网上有两者详细评测和激烈的讨论。

背景介绍完,说正题。

我们要实现一个模块,让它既能在seajs(CMD)环境里引入,又能在requirejs(AMD)环境中引入,

当然也能在Node.js(CommonJS)中使用,另外还可以在没有模块化的环境中用script标签全局引入。

首先一个模块看起来应该是这样:

当然,模块输出的不止可以是对象,还是可以是任何值,包括一个类。

分析CMD和AMD,我们需要提供一个工厂函数传入define来定义模块,所以变成这样:

为适应Node.js,可以来判断全局变量,由于require在CMD和ADM中都有定义,所以只判断:

typeof module !== ‘undefined‘ && typeof exports === ‘object‘

于是变成这样:

至此已经能够满足Node.js的需求。

当没有上述全局变量,且有define全局变量时,我们认为是AMD或CMD,可以直接将factory传入define:

注意:CMD其实也支持return返回模块接口,所以两者可以通用。

最后是script标签全局引入,我们可以将模块放在window上,

为了模块内部在浏览器和Node.js中都能使用全局对象,我们可以做此判断:

var global = typeof window !== ‘undefined‘ ? window : global;

同时,我们用一个立刻执行的闭包函数将所有代码包含,来避免污染全局空间,

并将global对象传入闭包函数,最终变成这样:

注意:闭包前加上分号是为了给前一个模块填坑,分号多了没问题,少了则语句可能发生变化。

于是同一个js文件我们能愉快的在不同环境这样引入:

但如果要定义的模块依赖其他模块,那就要在不同地方加上一些代码,并且不适应浏览器全局引入了。

时间: 2024-08-07 01:37:35

写一个适应所有环境的js模块的相关文章

用weexplus从0到1写一个app(2)-页面跳转和文章列表及文章详情的编写

说明 结束连续几天的加班,最近的项目终于告一段落,今天抽点时间开始继续写我这篇拖了很久的<用weexplus从0到1写一个app>系列文章.写这篇文章的时候,weexplus的作者已经把weexplus重构了一下,可以同时打包出web端和native端,我这边的ui界面和项目结构也跟着做了一点变化.这里有weexplus官方放出的一个电影APP的demo,有需要的可以去下载看看,然后顺便给weexplus一个star吧! 文章可能会很长,在此分几篇文章来写,先占个坑: 用weexplus从0到

如何发布一个自定义Node.js模块到NPM(详细步骤)

咱们闲话不多说,直接开始! 由于我从没有使用过MAC,所以我不保证本文中介绍的操作与MAC一致. 文章开始我先假定各位已经在window全局安装了Node.js,下面开始进行详细步骤介绍: 本文本着,以极少的文字说明以及极少的代码书写为原则来给大家演示! 文章中上传的模块不具备任何意义! 一.封装node.js模块时的必须项 1.创建package.json 每一个完整封装的node模块,必须含有一个参数明确的package.json文件! 以下为package.json的最精简配置: { "n

分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业不是百度来的,我只是百度了一些示例代码的意思,怎么用!算了,越解释万一越黑呢!哈哈O(∩_∩)O哈哈~) ----------------------------------------------------------------分界线------------------------------

Node.js(window)基础(2)——node环境下的模块,模块间调用

参考:http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434502419592fd80bbb0613a42118ccab9435af408fd000 1.node环境下的模块(module)概念:一个name.js文件就是一个模块,name是模块名称,模块中的函数方法称之为变量. 2.模块变量的调用:A.js中输出变量module.exports=函数名称; B.js引入模

JS入门学习,写一个时钟~

<!-- 耽搁了几天,于是又继续回到JS的学习了~~ 各种头大,加油吧... --> <!doctype html><html><head> <title>数码时钟</title> <meta charset="gb2312"> <style type="text/css"> *{ padding:0; margin:0;} body{background:rgb(0,2

js写一个通讯录

模拟通讯录列表功能 我们手机上面的通讯录列表里面都有根据右侧的字母跳滚动到该字母的第一个名单地方. 于是我把这个功能拆分成两个功能区思考: 第一个是如何把这些名字的的汉字首字母提取出来,并且把相同字母的汉字归类,最后显示成列表. 第二是右侧字母导航,它需要一直固定在右侧,并且我按一个字母,屏幕最中间会弹出一个字母方框,代表我选中了这个字母. 我首先去实现第一个问题,如何提取名字中第一个汉字的首字母? 我去尝试过许多种方法,其中尝试过使用localeCompare(),我也成功的排序了,但是我发现

[NodeJS]使用Node.js写一个简单的在线聊天室

声明:教程来自<Node即学即用>.源代码案例均出自此书.博文仅为个人学习笔记. 第一步:创建一个聊天server. 首先,我们先来写一个Server: var net = require('net') var chatServer = net.createServer() chatServer.on('connection',function(client){ client.write('connection~~~\n') client.end() }) chatServer.listen(

ThinkPHP环境下JS文件按模块部署

0.序言 一般来说,ThinkPHP的JS文件目录不是太友好:但允许修改参数确定JS的存放路径. 按照ThinkPHP的目录规范,JS文件一般视同静态资源处理,这样JS文件和视图htm文件将部署在两个完全不同的目录,即使二者属于同一应用.模块.通过Thinkphp提供的模板替换功能,配置模块的JS路径参数,可以将JS文件和普通视图文件都放在同一目录,例如Application/Module/View/目录下,这样在按应用.模块部署将变得更加便捷:两种文件所在位置比较接近,开发过程也相对比较方便(

【从头开始写操作系统系列】环境搭建以及第一个Hello World

写在最前 笔者在动手写此操作系统时是一名大学本科大二的学生,可能文章中会有好多地方我没有解释清楚,可能也会有许多地方出现错误,我恳请各位读者能提出质疑和纠正我的错误,谢谢! 参考书籍: <30天自制操作系统>川合秀实 <ORANGE'S:一个操作系统的实现> 开发环境 笔者采用以下开发环境 Apple Macbook Air Ubuntu 12.04 LTS(32 bit) 读者准备 毕竟是动手写一个操作系统,对读者的要求也会相应要求高一些,对计算机编程0基础的读者还是不建议直接看