【javascript激增的思考01】模块化编程
前言
之前我做过一个web app(原来可以这么叫啦),在一个页面上有很多小窗口,每个小窗口都是独立的应用,比如:
① 我们一个小窗口数据来源是腾讯微博,需要形成腾讯微博app小窗口
② 我们一个小窗口数据来源新浪微博,需要形成新浪微博的小窗口
我们注意到以上2个的数据源与处理方式较一致,但是需要做处理,而且其鉴权也不尽相同,所以这个js代码有相同的,也有不相同的。
③ 我们的一个小窗口数据来源于百度RSS,需要形成点击标题展开的功能
④ 我们一个小窗口数据来源于XXX,其表现形式为选项卡......
⑤ 我们一个小窗口是flash,需要......
⑥ 我们一个小窗口是个综合应用,里面还会有定时器,自动的更新其数据
......
① 点击最大化图标会最大化窗口,里面的数据滚屏分页
② 拖动排序,点击选择图标分配(导航上有不同的类)
③ 新闻预览,类似于google效果
④ 延迟加载
......
各位,这些功能都在一个页面呢,我们的js该怎么组织了,我们的js要怎么写才能让后来的人读的清晰呢?
然后,响应式布局流行了,小叶你去搞下,实现响应式布局!
然后,瀑布流很火,小叶不然把瀑布流也加上
然后,纯屏设计出来了,小叶,将我们的程序设置一下吧,用户可以选择自己想要的。。。
......
我们知道一个网站干不了这么多事情,但是一个公司不是研发最大,不是产品最大,而是老板最大!
老板说需要,那就必须需要,你不行就闪开,有人行。
我们这里先不说风云变幻的需求,就说以上应用,面对不停增加的不停种类的小窗口,我们应当如何组织,并且控制我们的javascript代码呢???
javascript之路
javascript最初使用并没有那么复杂,基本就是一个页面一个js解决问题,但是现在情况变了,我们的js现在需要干的事情不比后端少了,而且还有越来越多的趋势!
在这个时候很多后端的东西便直接上来了:
① MVC
② MVVM
③ 模块化编程
④ 设计模式
以上的提出都是为了更好的帮助前端兄弟组织自己的代码,但是我们知道一个事实:
设计模式这个东西没有几年扎实的功底根本就达不到一个高度,比如本人,在刚毕业时候还在搞.net便看了几本设计模式的书籍,自以为有所得,现在想来,尼玛的神马都不记得了!!!
所以,一个事实,前端很多兄弟,并且是比较优秀的兄弟,对设计模式了解不够深入啦(我反正不深)。
从优秀到高手的蜕变中,我们会写大量js代码,我们会发现,尼玛这一坨代码和那一坨代码好像长得有点像,
尼玛这三块代码感觉就只有一点差距啦!于是小钗就干过这个事情:
看着js里面有几块相同的,然后将它和到一个函数中了,并在函数中做了一点点变化,实现功能了,小钗看到少了几十行代码,小钗感到很高兴。
于是慢慢小钗在编程过程中有意无意的发现每次都会有几个家伙会重复,所以有一天小钗终于决定将至封装一番,从那以后,小钗遇到这个问题变不会写多余的代码了。
其实,通过以上的做法,优秀的程序员慢慢有了模块化编程的思想,或者面向对象编程的思维,刚开始以实现了很多的插件沾沾自喜,到后面点,就会站在框架与js/css代码的组织的高度审视整个项目的实现了。
这个时候他便是高手啦,但是有一段很长的路要走。。。
模块化编程
javascript时不存在类这种说法的,所以模块(module)就是一个传说(ECMAScipt第六版表示会支持)。
但是我们伟大的前端技术人员模拟实现了类这个家伙,最后还实现了模块这个家伙。
最初的想法:模块就是实现特定功能的一组方法
- function m1() {}
- function m2() {}
将上面两个函数加在一起,便可直接调用,但是我们知道这种做法会导致全局对象污染,所以我们换个做法:
- var person = {
- name: '叶小钗',
- getName: function () {},
- setName: function () {}
- };
这样做又会导致内部的局部变量会被外部篡改,这显然不够“oop”,我们知道javascript唯一可以产生局部作用域的方式便是函数,所以我们有了这种写法:
- var Person = (function () {
- var name='叶小钗';
- var getName: function () {};
- var setName: function () {};
- return {get: getName, set: setName};
- })();
如此一来,我们内部的的变量就老实了,这样看上去也比较面向对象啦。
以上就是我们模块化编程的基本做法,下面来一点点变化,因为我们的模块可能会很大的:
当模块很大时,便需要用到“放大模式”,这些高级概念我们后面点再去理解。
- var person = (function (mod) {
- mod.getAge = function () {};
- ......
- })(Person);
我们看到我们原来是没有age这个变量的,所以我们一个模块需要用到的变量最好能在上面定义。
异步问题
以上的方式其实比较乐观,但是我们很多时候其实并不能保证person已经被定义了,所以上面的用法可能是错误的,这在异步编程模型中会经常遇到,这个时候我们有了一个“宽放大模式”:
- var person = (function (mod) {
- mod.getAge = function () {};
- ......
- })(Person || {});
做了一点点的变化,但是整个程序的容错度上升了。
模块化的重要性
模块化后,我们可以方便的使用其他同事的代码,也不必担心命名污染的问题了,目前通行的javascript模块规范有两种:CommonJS与AMD。
node.js这一神器的产物的诞生(我后面点会针对此写一个系列的文章,在此叮嘱自己),标志着javascript模块化编程正式诞生,因为网页一般不会很复杂,服务器的话,没有模块便做死吧。。。。
node.js的模块系统是参照CommonJS规范实现的,在CommonJS中有一个全局性方法require(),用于加载模块。
若是有一数学模块math.js,便可以如此解决:
- var math = require('math');
- math.add(1, 4);
若是要搞node.js的兄弟先从这个家伙开始吧。
客服端的疑惑
以上的代码,我们知道第一行其实是会加载一段math.js的函数的,意思是我们下面的math.add要等到文件加载结束才行啦。。。这就是同步加载与异步加载的痛苦。
我们知道好的网站是不能容忍“假死”的,但是我们并不能知道网速等因素,所以同步的话,浏览器必定会假死,异步加载模型再一次出现{asynchronous},传说中的AMD。
AMD:Asynchronous Module Definition
异步模块定义,他采用异步方式加载模块,模块加载不影响后面语句执行,其实我们对他的实现应该非常熟悉的,想想我们的ajax啦:
- require('math', function (math) {
- math.add();
- });
这个内部发生了什么大家应该一目了然,应该和$.getScript是一个原理的。于是我们来介绍一个实现了AMD的javascript库:require.js。
PS:初步印象,这样虽然是按需加载的,但是以我们之前小窗口的需求来说,我们可能每一个小窗口会对应一个js文件,页面小窗口过多(延迟加载可以忽略),可能导致同时加载几个js会不会对性能有影响吗?这里我们先不关注他。
我们来看看我们的require.js,他的提出为了解决以下问题:
① 实现javascript异步加载,避免页面假死
② 管理模块之间的依赖性,便于代码编写与维护(这是重点啊)
要使用require.js需要下载最新的版本。这里比较重要,我们单独开一段吧
require.js
我们先去官网下载脚本:http://requirejs.org/docs/release/2.1.6/r.js
他这个最让人兴奋的就是,我们可以如此指定一个头main入口文件:
- <script src="js/require.js" data-main="js/main"></script>
比如我现在会一次性加载几个js文件:
- require (['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
- // some code here
- });
以上是主模块依稀三个模块的写法,若是主模块依赖于jquery的话:
- require(['jquery'], function ($) {
- });
AMD模块写法
require.js加载采用AMD规范,假定有一个math.js文件,他定义了一个math模块,那么math需要这样写:
- //math.js
- define(function () {
- var func = function () {};
- return {func: func};
- });
- //加载方式
- require(['math'], function (math) {
- //...
- })
算了,关于require.js这块东西,我等下做几个例子再跟进吧,现在都不熟悉,说这么多也没用。
结语
这块东西我们暂时说道这里,接下来我们来使用一番require.js,以及来说下MVC与MVVM是神马东西吧。
参考:
http://kb.cnblogs.com/page/161717/
【javascript激增的思考01】模块化编程的更多相关文章
- JavaScript学习笔记-面向对象的模块化编程
面向对象的模块化编程 模块是一个独立的JS文件,模块文件可以包含一个类定义.一组相关的类.一个实用函数库.一些待执行的代码 模块化的目标:支持大规模的程序开发,处理分散源代码的组装,并能让代码正确执行 ...
- 【javascript激增的思考02】模块化与MVC
前言 之前我们遇到了这么一个项目,也就是我们昨天提到的,有很多的小窗口的,昨天说的太抽象了,今天我们再来理一理什么是小窗口(后面点说下),当时由于js有一点复杂,我自己也装B跟风用了一下传说中MVC! ...
- 【javascript激增的思考04】MVC与Backbone.js(beta)
前言 最近整理了很多前端面试题的东西,今天又去参加了一次面试,不知各位烦不烦,我反正有点累了,于是我们今天继续回到我们前段时间研究的问题,我们再来看看MVC吧. 什么是MVC 又回到这个问题了,到底什 ...
- 【javascript激增的思考03】MVVM与Knockout
前言 今天搞的有点快,因为上午简单研究了下MVC,发现MVC不太适合前端开发,然后之前看几位前端前辈都推荐前端使用MVVM,但是我对其还不甚了解,所以我觉得下午还是应该先看看他是神马先,后面再决定要不 ...
- 深入了解Javascript模块化编程
本文译自Ben Cherry的<JavaScript Module Pattern: In-Depth>.虽然个人不太认同js中私有变量存在的必要性,但是本文非常全面地介绍了Javascr ...
- Javascript模块化编程详解
在这篇文章中,我将会回顾一下js模块化编程的基础,并且将会讲到一些真的非常值得一提的进阶话题,包括一个我认为是我自创的模式. 模块化编程是一种非常常见Javascript编程模式.它一般来说可以使得代 ...
- Javascript模块化编程(三):require.js的用法
Javascript模块化编程(三):require.js的用法 原文地址:http://www.ruanyifeng.com/blog/2012/11/require_js.html 作者: 阮一峰 ...
- Javascript模块化编程(二):AMD规范
Javascript模块化编程(二):AMD规范 作者: 阮一峰 原文地址:http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_d ...
- Javascript模块化编程(一):模块的写法
Javascript模块化编程(一):模块的写法 作者: 阮一峰 原文链接:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html ...
随机推荐
- javascript语句——条件语句、循环语句和跳转语句
× 目录 [1]条件语句 [2]循环语句 [3]跳转语句 前面的话 默认情况下,javascript解释器依照语句的编写顺序依次执行.而javascript中的很多语句可以改变语句的默认执行顺序.本文 ...
- vc++用ADO方式连接oracle问题
今天装了个oracle客户端,准备写个访问远程oracle的程序.用的是vs2010,采用ADO的连接方法连接oracle,结果运行的时候总是报下面的错: 从提示可以看出是没有找到OraOLEDBup ...
- SQL*Loader之CASE1
最近项目涉及到将文本文件中的数据导入到Oracle数据库中,故研究了下SQL*Loader,官档提供的资料不是很丰富,很多案例中出现的语句在官档中找不到出处.但它提供的案例本身却彰显出了SQL*Loa ...
- Dijkstra算法(一)之 C语言详解
本章介绍迪杰斯特拉算法.和以往一样,本文会先对迪杰斯特拉算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法 ...
- 从重置input file标签中看jQuery的 .val() 和 .attr(“value”) 区别
背景: 在清空input file标签选中值时,分别用了以下方法,发现有的对有的错: [√]$("#file")[0].value = ""; [√]$(&qu ...
- WPF The Hard Way
WPF The Hard Way Windows Presentation Foundation (WPF) 是微软下一代显示系统,用于生成能带给用户震撼视觉体验的 Windows 客户端应用程序. ...
- CentOS7 Nexus安装
CentOS7 Nexus安装 CentOS7 Nexus安装 Download 从Nexus下载nexus-2.11.2-03-bundle.tar.gz Install 安装 上传RPM文件到/t ...
- 在SQL Server 2014里,如何用资源调控器压制你的存储?
在今天的文章里,我想谈下SQL Server 2014里非常酷的提升:现在你终于可以根据需要的IOPS来压制查询!资源调控器(Resource Governor)自SQL Server 2008起引入 ...
- ASP.NET 文件下载
using System; using System.Web; using System.IO; public partial class _Default : System.Web.UI.Page ...
- EDNS
随着业务的复杂化和多样化,RFC1035中定义的DNS消息格式和它支持的消息内容已经不足以满足一些DNS服务器的需求,于是,RFC2671中提出了一种扩展DNS机制EDNS(Extension Mec ...