【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 ...
随机推荐
- 带毫秒的字符转换成时间(DateTime)格式的通用方法
C#自身有更好的方式,Net任意String格式转换为DateTime类型 ====================================================== 原文 ==== ...
- PHP面向对象中的重要知识点(三)
1. namespace: 和C++中的名字空间很像,作用也一样,都是为了避免在引用较多第三方库时而带来的名字冲突问题.通过名字空间,即便两个class的名称相同,但是因为位于不同的名字空间内,他们仍 ...
- 自绘制HT For Web ComboBox下拉框组件
传统的HTML5的下拉框select只能实现简单的文字下拉列表,而HTforWeb通用组件中ComboBox不仅能够实现传统HTML5下拉框效果,而且可以在文本框和下拉列表中添加自定义的小图标,让整个 ...
- 日志插件 log4net 的使用
文本格式说明 可以记载的日志类别包括:FATAL(致命错误).ERROR(一般错误).WARN(警告).INFO(一般信息).DEBUG(调试信息). 文本参数说明 %m(message):输出的日志 ...
- 使用.NET 4.0+ 操作64位系统中的注册表
一.64位系统中的注册表 以 LocalMachine 中的启动项为例: 64位应用的注册表位置还是在: SOFTWARE\Microsoft\Windows\CurrentVersion\Run 而 ...
- WCF双工通讯以及客户端间的间接通讯
由于学习计划安排不当,对WCF的认知一直停滞不前,最近工作上又用回了WCF,重拾一下,看到蒋老师介绍双工通讯的博文,实践一下,积累一下.原想着WCF的双工通讯就是原本的客户端能调用服务端的方法之余,服 ...
- Android经典完美退出方法
Android经典完美退出方法,使用单例模式创建一个Activity管理对象,该对象中有一个Activity容器(具体实现自己处理,使用LinkedList等)专门负责存储新开启的每一个Activit ...
- 通过泛型数据,操作SQL数据库
本人在操作数据库的时候,采用将对象的形式操作传入数据库,经过大量百度和朋友帮助,总结出如下两个接口.用于插入数据,提取数据. 要这样操作的前提条件,就是类名和表名一致,类字段和表字段一致就可以了 // ...
- Android文件的分割和组装
使用UDP数据包发送文件时,由于UDP数据包大小的限制,一个文件要放在几个UDP数据包里面发送,这就需要把一个文件分割成若干部分,分别放进若干个UDP数据包里面,在接收端,收到这些UDP数据包以后,再 ...
- 【Java每日一题】20161020
20161019问题解析请点击今日问题下方的"[Java每日一题]20161020"查看 package Oct2016; public class Ques1020 { publ ...