长期以来JavaScript语言本身不提供模块化的支持, ES6中终于给出了 from, import等关键字来进行模块化的代码组织。 但CommonJS、AMD等规范已经被广为使用,如果希望你的JavaScript同时支持浏览器和Node.js, 现在只有这几种方式:

通过 browserify等工具进行转换。 提供浏览器端CommonJS框架,比如这个简易的 CommonJS 实现。 通过小心的编码来支持多种环境。

browserify几乎可以保证Node.js下测试通过的代码在浏览器中仍然能够正常使用。 但缺点也很显然:很容易产生冗余代码并生成一个巨大的JavaScript库。 对于微型的JavaScript工具,小心地编码再合适不过了!见下文。

避开全局的名称空间

CommonJS中,每个源文件中的局部变量在其他文件中不可见。 然而浏览器中,所有全局名称空间的变量对所有JavaScript文件都可见。 这意味着我们需要包装所有的代码。例如:

(function(){ // your code goes here...})();

不同于常见编程语言,JavaScript采取函数作用域, 用一个 function来包裹你的代码可以隐藏里面的局部变量。

如果你对整个文件都被缩进的代码很反感,可以在构建时再添加上述代码。例如Makefile中:

person.js: index.js echo '(function(){' > $@ cat $^ >> $@ echo '})();' >> $@

如果你对Make构建前端项目感兴趣,可以看看Harttle的尝试:Makefile构建前端项目

一个简单的类

当然,『类』指的就是一个函数。假设我们的JavaScript模块提供一个叫做 Person的类:

(function(){ function Person(){ this.name = 'harttle'; }})();

下文将会考虑如何将这个类提供给其他模块使用。

检测CommonJS环境

要使用 typeof来检测一个变量是否曾被声明,因为 if对于未声明的变量会抛出错误。 例如:

// Uncaught ReferenceError: foo is not definedif(foo == undefined){ console.log('foo does not exist');}// 正常运行if(typeof foo == 'undefined'){ console.log('foo does not exist');}

检测CommonJS我们只需要检测 module, exports, require是否存在,比如:

// CommonJSif (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { module.exports = Person;} 检测浏览器环境

浏览器环境也包括引入了AMD框架的,以及没有做模块化的。 对于前者我们应当使用AMD框架来声明一个模块,而对于后者我们只需要暴露一个全局变量。

// Browserif (typeof define === 'function' && define.amd) { define('Person', [], function() { return Person; });} else { window.Person = Person;}

当然这些浏览器检测相关逻辑也应当一并包裹在 function中。

编写浏览器和Node.js通用的JavaScript模块的更多相关文章

  1. 如何写兼容浏览器和Node.js环境的Javascript代码

    如果有打开过jQuery的源码(从1.11及以后),或者Vue.js.React.js的源码,都会在文件的前面看见这样一段代码: ( function( global, factory ) { &qu ...

  2. 使用node.js 进行服务器端JavaScript编程

            node.js 入门        node.js 可以运行在 Linux.Windows 和 Macintosh 等主流的操作系统上.在 Windows 平台上运行 node.js ...

  3. 编写原生的Node.js模块

    导语:当Javascript的性能遭遇瓶颈,或者需要增强Javascript能力的时候,就需要依赖native模块来实现了. 应用场景 日常工作中,我们经常需要将原生的Node.js模块做为依赖并在项 ...

  4. node.js第二天之模块

    一.模块的定义 1.在Node.js中,以模块为单位划分所有功能,并且提供了一个完整的模块加载机制,这时的我们可以将应用程序划分为各个不同的部分. 2.狭义的说,每一个JavaScript文件都是一个 ...

  5. node.js(七) 子进程 child_process模块

    众所周知node.js是基于单线程模型架构,这样的设计可以带来高效的CPU利用率,但是无法却利用多个核心的CPU,为了解决这个问题,node.js提供了child_process模块,通过多进程来实现 ...

  6. node.js中使用http模块创建服务器和客户端

    node.js中的 http 模块提供了创建服务器和客户端的方法,http 全称是超文本传输协议,基于 tcp 之上,属于应用层协议. 一.创建http服务器 const http = require ...

  7. 创业笔记-Node.js入门之JavaScript与Node.js

    JavaScript与Node.js JavaScript与你 抛开技术,我们先来聊聊你以及你和JavaScript的关系.本章的主要目的是想让你看看,对你而言是否有必要继续阅读后续章节的内容. 如果 ...

  8. Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

    从浏览器中创建 XMLHttpRequests 从 node.js 创建 http 请求 支持 Promise API 拦截请求和响应 转换请求数据和响应数据 取消请求 自动转换 JSON 数据 客户 ...

  9. 基于promise用于浏览器和node.js的http客户端的axios

    axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征: 从浏览器中创建 XMLHttpRequest 从 node.js 发出 http 请求 支 ...

随机推荐

  1. Android我的便签-----SQLite的使用方法

    在Android开发中也有数据库的存在,最近有空,把以前写的一个便签来讲述一下Android中的数据库,跟大家分享分享的,希望对大家有所帮助. SQLite简介 SQLite,是一款轻量级的关系型数据 ...

  2. Hessian序列化

    当子类定义了和父类同名的属性时,经过hessian传输,会导致该属性值丢失.因为hessian发送二进制数据时,子类数据在前,父类数据在后.接收二进制数据时,子类数据在前,父类数据在后.所以对于同名字 ...

  3. java反射调用api

    cglib的fastmethod 简单示例: FastClass serviceFastClass = FastClass.create(Person.class); Person p = new P ...

  4. HDU 5793 A Boring Question (找规律 : 快速幂+乘法逆元)

    A Boring Question Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  5. 【LeetCode 228_数组】Summary Ranges

    vector<string> summaryRanges(vector<int>& nums) { int nums_len = nums.size(); vector ...

  6. 使用CGLib完成代理模式遇到的错误

    错误堆栈信息: Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type ...

  7. python中sort()与sorted()的区别

    Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列 一,最简单的排序 1.使用sort排序 my_list = [3 ...

  8. PostgreSQL监控脚本

    往往我们对着一堆系统状态视图不知所措,这里我整理一些学习到的脚本: 后续慢慢补充- --20170913--这部分参考了http://blog.postgresql-consulting.com pg ...

  9. 【跟着stackoverflow学Pandas】“Large data” work flows using pandas-pandas大数据处理流程

    最近做一个系列博客,跟着stackoverflow学Pandas. 以 pandas作为关键词,在stackoverflow中进行搜索,随后安照 votes 数目进行排序: https://stack ...

  10. 关于Gradle2.0的翻译说明

    Gradle1.12的翻译情况 Gradle实际上在4月16日就已经在对应的OmegaT项目上完成了翻译,后因项目繁忙,直到7月20日才完成了Github上Gradledoc项目及七牛站点的更新. 总 ...