Javascript模块化编程

  随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂。
Javascript模块化编程 - 梁敬承 - 梁敬承技术笔记

网页越来越像桌面程序,需要一个团队分工协作、进度管理、单元测试等等......开发者不得不使用软件工程的方法,管理网页的业务逻辑。

Javascript模块化编程,已经成为一个迫切的需求。理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块。

但是,Javascript不是一种模块化编程语言,它不支持"类"(class),更遑论"模块"(module)了。(正在制定中的ECMAScript标准第六版,将正式支持"类"和"模块",但还需要很长时间才能投入实用。)

Javascript社区做了很多努力,在现有的运行环境中,实现"模块"的效果。本文总结了当前"Javascript模块化编程"的最佳实践,说明如何投入实用。虽然这不是初级教程,但是只要稍稍了解Javascript的基本语法,就能看懂。

Javascript模块化编程 - 梁敬承 - 梁敬承技术笔记

一、原始写法

模块就是实现特定功能的一组方法。

只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块。

  function m1(){
    //...
  }

  function m2(){
    //...
  }

上面的函数m1()和m2(),组成一个模块。使用的时候,直接调用就行了。

这种做法的缺点很明显:"污染"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。

二、对象写法

为了解决上面的缺点,可以把模块写成一个对象,所有的模块成员都放到这个对象里面。

  var module1 = new Object({

    _count : 0,

    m1 : function (){
      //...
    },

    m2 : function (){
      //...
    }

  });

上面的函数m1()和m2(),都封装在module1对象里。使用的时候,就是调用这个对象的属性。

  module1.m1();

但是,这样的写法会暴露所有模块成员,内部状态可以被外部改写。比如,外部代码可以直接改变内部计数器的值。

  module1._count = 5;

三、立即执行函数写法

使用"立即执行函数"(Immediately-Invoked Function Expression,IIFE),可以达到不暴露私有成员的目的。

  var module1 = (function(){

    var _count = 0;

    var m1 = function(){
      //...
    };

    var m2 = function(){
      //...
    };

    return {
      m1 : m1,
      m2 : m2
    };

  })();

使用上面的写法,外部代码无法读取内部的_count变量。

  console.info(module1._count); //undefined

module1就是Javascript模块的基本写法。下面,再对这种写法进行加工。

四、放大模式

如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式"(augmentation)。

  var module1 = (function (mod){

    mod.m3 = function () {
      //...
    };

    return mod;

  })(module1);

上面的代码为module1模块添加了一个新方法m3(),然后返回新的module1模块。

五、宽放大模式(Loose augmentation)

在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上一节的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用"宽放大模式"。

  var module1 = ( function (mod){

    //...

    return mod;

  })(window.module1 || {});

与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象。

六、输入全局变量

独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。

为了在模块内部调用全局变量,必须显式地将其他变量输入模块。

  var module1 = (function ($, YAHOO) {

    //...

  })(jQuery, YAHOO);

上面的module1模块需要使用jQuery库和YUI库,就把这两个库(其实是两个模块)当作参数输入module1。这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显。这方面更多的讨论,参见Ben Cherry的著名文章《JavaScript Module Pattern: In-Depth》。

七、模块的规范

先想一想,为什么模块很重要?

因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。

但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写法,岂不是乱了套!考虑到Javascript模块现在还没有官方规范,这一点就更重要了。

目前,通行的Javascript模块规范共有两种:CommonJS和AMD。我主要介绍AMD,但是要先从CommonJS讲起。

八、CommonJS

2009年,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程。

Javascript模块化编程 - 梁敬承 - 梁敬承技术笔记

这标志"Javascript模块化编程"正式诞生。因为老实说,在浏览器环境下,没有模块也不是特别大的问题,毕竟网页程序的复杂性有限;但是在服务器端,一定要有模块,与操作系统和其他应用程序互动,否则根本没法编程。

node.js的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。假定有一个数学模块math.js,就可以像下面这样加载。

  var math = require('math');

然后,就可以调用模块提供的方法:

  var math = require('math');

  math.add(2,3); // 5

因为这个系列主要针对浏览器编程,不涉及node.js,所以对CommonJS就不多做介绍了。我们在这里只要知道,require()用于加载模块就行了。

九、浏览器环境

有了服务器端模块以后,很自然地,大家就想要客户端模块。而且最好两者能够兼容,一个模块不用修改,在服务器和浏览器都可以运行。

但是,由于一个重大的局限,使得CommonJS规范不适用于浏览器环境。还是上一节的代码,如果在浏览器中运行,会有一个很大的问题,你能看出来吗?

  var math = require('math');

  math.add(2, 3);

第二行math.add(2, 3),在第一行require('math')之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里等。

这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态。

因此,浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"(asynchronous)。这就是AMD规范诞生的背景。

十、AMD

AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:

  require([module], callback);

第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:

  require(['math'], function (math) {

    math.add(2, 3);

  });

math.add()与math模块加载不是同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。

目前,主要有两个Javascript库实现了AMD规范:require.js和curl.js。

转自:

http://www.ruanyifeng.com/blog/2012/10/javascript_module.html

http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499993.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zookeeper基础整理

zookeeper简述 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件 ZooKeeper 使用 Java 所编写,但是支持 Java 和 C 两种编程语言。 提供的功能包括&#xf…

JS模块化编程require.js简介

一、为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了。后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载。下面的网页代码&…

CSS position属性

目前几乎所有主流的浏览器都支持position属性("inherit"除外,"inherit"不支持所有包括IE8和之前版本IE浏览器,IE9、IE10还没测试过),以下是w3school对position五个值的解释: 其中absol…

storm的并行度的解释--- ( 看完就能理解 )

关于storm的基础,参照我这篇文章:流式计算storm 关于并发和并行,参照我这篇文章:并发和并行 关于storm的并行度解释,参照我这篇文章:storm的并行度解释 关于storm的流分组策略,参照我这篇文章:storm的流分组策略 关于storm的消息可靠机制,参照我这篇文章:storm的消息可靠机…

jQuery选择器总结

jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法 最基本的: $("#myELement") 选择id值等于myElement的元素,id值不能重复在文档中只能有一个id值是myElement所以得到的是唯一的元素 $("div") …

storm的流分组策略

关于storm的基础,参照我这篇文章:流式计算storm 关于并发和并行,参照我这篇文章:并发和并行 关于storm的并行度解释,参照我这篇文章:storm的并行度解释 关于storm的流分组策略,参照我这篇文章:storm的流分组策略 关于storm的消息可靠机制,参照我这篇文章:storm的消息可靠机…

CSS串联和后代选择器

串联选择器&#xff1a;作用在同一个标签上复制代码代码如下:<div class”a” id "qq"><span>look at the color</span></div></p> <p>css: #qq.a{….}后代选择器&#xff1a;作用在不同标签上复制代码代码如下:<div id &quo…

storm消息可靠机制(ack)的原理和使用

关于storm的基础,参照我这篇文章:流式计算storm 关于并发和并行,参照我这篇文章:并发和并行 关于storm的并行度解释,参照我这篇文章:storm的并行度解释 关于storm的流分组策略,参照我这篇文章:storm的流分组策略 关于storm的消息可靠机制,参照我这篇文章:storm的消息可靠机…

JS--Console.log()详解

对于JavaScript程序的调试&#xff0c;相比于alert()&#xff0c;使用console.log()是一种更好的方式&#xff0c;原因在于&#xff1a;alert()函数会阻断JavaScript程序的执行&#xff0c;从而造成副作用&#xff1b;而console.log()仅在控制台中打印相关信息&#xff0c;因此…

订单单量监控v2

前段时间做了一个订单单量监控的项目,已经投入使用了,现在总结一下 前期的想法参考这篇文章 整体使用了storm实时计算框架和redis数据库,还有kafka消息队列 先上效果图,我们可以后期将数据展示出来,明显发现某天00点有单量突变的情况,明显是促销活动导致单量增加了 而后面的报…

AFNetworking 3.0迁移指南

AFNetworking是一款在OS X和iOS下都令人喜爱的网络库。为了迎合iOS新版本的升级, AFNetworking在3.0版本中删除了基于 NSURLConnection API的所有支持。如果你的项目以前使用过这些API&#xff0c;建议您立即升级到基于 NSURLSession 的API的AFNetworking的版本。本指南将引导您…

想法记录---实时计算的TopN的实现

TopN就是找出时间段内出现频率最高的n个 TopN的计算是个老生常谈的话题,比如微博的热搜,都是隔段时间就统计一次TopN 现在想做一个实时计算的TopN. 先说说离线计算的TopN,再说实时TopN 离线TopN 离线TopN一般出现在大数据的应用场景,使用hadoop的map reduce,网上有很多案例 …

iOS中的MVC设计模式

一、MVC概述模型&#xff0d;视图&#xff0d;控制器&#xff08;MVC&#xff09;是Xerox PARC在二十世纪八十年代为编程语言Smalltalk&#xff0d;80发明的一种软件设计模式&#xff0c;已被广泛使用。后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式&#xff0c;并且受到…

java 时间的相关转换操作

关于时间的操作,写了个util 主要用于预测的时候,时间段的确定 预测的时间段,需要明确的规定范围,由于业务的促销都是整点开始,所以我们的预测时间段,也是从整点开始 所以就要将时间分为多个整段,比如一分钟一段,那么就是2018-06-18 00:00:00 到2018-06-18 00:01:00 就是一段 那…

iOS-MVVM-模式介绍

一、MVVM概述 MVVM 到底是什么&#xff1f;我们首先看一下MVC架构&#xff1a;我们看到的是一个典型的 MVC 设置。Model 呈现数据&#xff0c;View 呈现用户界面&#xff0c;而 View Controller 调节它两者之间的交互。Cool&#xff01;稍微考虑一下&#xff0c;虽然 View 和 …

[数据库]---mysql数据库 使用binlog+canal或binlake进行数据库的复制

前言 在进行冷热分离的时候&#xff0c;需要将数据实时的复制在历史数据库中&#xff0c;我们使用的是binlogcanal的思想,将每次数据库数据的变更转换成消息发出来,然后再操作这些消息达到数据复制的 在京东,实现同样功能的组件&#xff0c;叫binlake 接下来详细说下: 1.Binl…

加密算法概念简介--MD5、SHA、DES、3DES、AES、RSA、ECC

MD5MD5即Message-Digest Algorithm 5&#xff08;信息-摘要算法5&#xff09;&#xff0c;用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一&#xff08;又译摘要算法、哈希算法&#xff09;&#xff0c;主流编程语言普遍已有MD5实现。将数据&#xff08;如汉字&…

MAC下配置ZSH

MAC下面的终端是神器。而且苹果非常贴心的为我们准备好了ZSH。 可惜ZSH不是很好用&#xff0c;需要配合一些插件和模板&#xff1a;oh-my-zsh将bash切换为zsh chsh -s /bin/zsh其实还可以用which来定位&#xff08;特别是ubuntu的童鞋&#xff09; chsh -s which zsh 直接用zsh…

搭建: canal部署与实例运行

搭建&#xff1a; canal部署与实例运行 数据库读log同步用 详见下面

MAC下使用OpenSSL生成私钥和公钥

MAC OS自带了OpenSSL,直接在命令行里使用OPENSSL就可以。打开命令行工具&#xff0c;然后输入 openssl打开openssl&#xff0c;接着只要三句命令就可以搞定。1、打开Terminal--cd 到指定文件夹&#xff0c;如桌面Mac:~/Desktop $ openssl2、第一句命令&#xff1a;生成私钥&…