前言

都说“不重复造轮子”,就像iPhone——它除了打电话还可以播放音乐——但是工程师不用从零开始做一个音乐播放功能,也许只要在iPhone的系统中整合一个ipod。

前端开发亦是如此,最理想化的开发状态就是,工程师只写核心业务代码,其他通用的功能和组件都可以无缝加载别人写好的代码,就像很多那样。

可是实际情况是,有个糟糕的 iPhone 工程师,他搞混了 iPhone 和 ipod 的系统,甚至把 iPhone 的 Home 键和 iPod 的音量键焊在同一个。

还有一些糟糕 JavaScript 开发者,一不小心声明了全局变量,混乱了“命名空间”,都让协作开发变得不那么友好,抑或他开发了一个通用模块,用户们却发现载入了他的代码之后,用户自己的代码被他搞得一团糟。

原始人写法

比如下面这段代码:

var mylove = "coding";

function getLove() {
return mylove;
} function sayLove(thing) {
console.log(thing);
} console.log(getLove());//>>> coding
sayLove('girl');//>>> girl

在 window 对象下声明了一个变量 mylove ,然后使用 getLove() 函数去获取这个变量,使用 setLove() 修改这个变量。

恩,功能是实现了。只是这样做之后,说不定什么时候你由于粗心又在某个地方声明了一次 mylove ,而你的粗心同事也不知道会在什么地方写了一个同名函数——也许有3个参数的 setLove() 函数。

对象封装写法

怎么办呢?你获取想到了,把这些变量和函数都写在一个对象里:

var loveThing = {
mylove : "coding",
getLove :function() {
return this.mylove;
},
sayLove : function(thing) {
console.log(thing);
}
} console.log(loveThing.getLove());//>>> coding
loveThing.sayLove('girl');//>>> girl

这种写法已经有点模块的样子了,一下就能看出这几个函数和变量之间的联系。缺点在于所有变量都必须声明为公有,所以都要加this指示作用域以引用这些变量。更危险的是,在对象之外也能轻松更改里面的参数:

loveThing.mylove = "sleeping";
console.log(loveThing.getLove());//>>> sleeping

立即执行函数

我向来不惮以最坏的恶意揣测程序员,你永远想不到你的 partner 会不会真的在其他地方修改了你的参数,也不知道自己是否会在不经意间修改了他的。我们必须在他下手之前——让自己的模块先执行掉,不给对方可趁之机。此时使用一种叫做 立即执行函数 的办法,可以避免暴露私有成员。

var loveThing = (function(){
var my = {};
var love = "coding";
my.getLove = function() {
return love;
}
my.sayLove = function(thing) {
console.log(thing);
}
return my;
})(); console.log(loveThing.getLove());//>>> coding
loveThing.sayLove('reading');//>>> reading

我们试着获取里面的变量:

console.log(loveThing.love);//>>> undefined

果然,外部根本看不见里面的零件,只能使用提供的接口。这样才能保证私有变量的安全。

放大模式

当然,一个项目要用到模块化的时候,说明这个项目足够大足够复杂,一个模块可能需要继承另一个模块,或者扩充模块,这时候需要使用 放大模式 :

var loveThing = (function (o){
o.sayOK = function () {
console.log('OK');
};
return o;
})(loveThing); loveThing.sayOK();//>>> OK!

宽放大模式

可是,浏览器是一个不按常理出牌的环境,你永远不知道自己引用的模块是否已经加载。万一我之前的 loveThing 没有被加载,上面这段代码就会报错了(找不到对象)。解决方法就是所谓 宽放大模式 :

var loveThing = (function (o){
o.sayOK = function () {};
return o;
})(loveThing || {});

与之前唯一的不同就是参数可以为空对象。

至此,最基本的JavaScript模块化写法你已经学会了,相信你也体会到自己原来的写法有什么不足。

受篇幅限制,本篇入门到此结束,我会在下一篇讨论流行的模块化规范。

造轮子和用轮子:快速入门JavaScript模块化的更多相关文章

  1. jxa快速入门,Javascript已加入AppleScript全家桶

    因为工作环境基本是以跨平台为主,所以纯mac本地化的AppleScript一直关注是不够的,前几天找资料发现AppleScript也在迅速的进步着,目前已经对Javascript做了比较好的支持--- ...

  2. 前端零基础快速入门JavaScript

    JavaScript代码可以直接嵌在网页的任何地方,不过通常我们都把JavaScript代码放到<head>中: <html><head> <script&g ...

  3. (18/24) webpack实战技巧:快速入门webpack模块化配置

    搞个小例子便于学习: 具体操作为把上节中的webpack.config.js中的entry入口文件进行模块化设置,单独拿出来制作成一个模块. 1.在根目录新建一个config文件,然后新建webpac ...

  4. html5快速入门(四)—— JavaScript

    前言: 1.HTML5的发展非常迅速,可以说已经是前端开发人员的标配,在电商类型的APP中更是运用广泛,这个系列的文章是本人自己整理,尽量将开发中不常用到的剔除,将经常使用的拿出来,使需要的朋友能够真 ...

  5. JavaScript快速入门(四)——JavaScript函数

    函数声明 之前说的三种函数声明中(参见JavaScript快速入门(二)——JavaScript变量),使用Function构造函数的声明方法比较少见,我们暂时不提.function func() { ...

  6. IdentityServer4 中文文档 -15- (快速入门)添加 JavaScript 客户端

    IdentityServer4 中文文档 -15- (快速入门)添加 JavaScript 客户端 原文:http://docs.identityserver.io/en/release/quicks ...

  7. 【JavaScript】快速入门

    摘抄地址快速入门 No1: JavaScript严格区分大小写 No2: JavaScript不区分整数和浮点数,统一用Number表示 NaN表示Not a Number,当无法计算结果时用NaN表 ...

  8. 造个简单的轮子倒是不难,但可用性健壮性高到qt这样全世界都在用,就几乎不可能了

    造个简单的轮子倒是不难,但可用性健壮性高到qt这样全世界都在用,就几乎不可能了比如自己写个事件循环实现信号槽,还真不难,我这边的架构里就这么搞了个仿osgi的事件总线嵌入式实时操作系统上能用的大型gu ...

  9. RPC基础以及造一个RPC的轮子需要注意些什么

    RPC基础以及造一个RPC的轮子需要注意些什么 前言 rpc即远程过程调用,是分布式系统常用的通信方法.远程可以是在一台机器上的不同进程或在不同一个机器上的不同进程.rpc更看重速度,像调用本地方法一 ...

随机推荐

  1. oracle使用using关键字

    oracle使用using关键字sql/92标准可以使用using关键字来简化连接查询,但是只是在查询满足下面两个条件时,才能使 用using关键字进行简化.1.查询必须是等值连接.2.等值连接中的列 ...

  2. nginx-1.12.1编译参数详情

    一下nginx-1.12.1编译参数详情 #/usr/local/nginx/sbin/nginx -V nginx version: nginx/1.12.1 built by gcc 4.4.7 ...

  3. javascript 伪数组与标准数组

    伪数组 1. 是一个对象 2. 必须有length 属性,length 值是number 类型 3. 如果这个对象的length 不为0,那么必须要有按照下标存储的数据 标准数组 判断数据是否是标准数 ...

  4. js 定义像java一样的map方便取值【转】

    js 定义像java一样的map方便取值.  百度有位大神说"js对象本身就是一种Map结构",这真是一段让人欢天喜地的代码. <script> //定义一个全局map ...

  5. CentOS6.x网易163yum源配置

    一.备份原yum源 [root@yancy ~]# mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.$(d ...

  6. ThreadLocal以及内存泄漏

    ThreadLocal是什么 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用Thr ...

  7. webstorm 很卡 scanning files to index (扫描文件索引)

    webstorm 号称"前端神器",但npm导入包跑索引,会很卡不停的跑索引... 排除你不想索引的文件夹 找到你想排除的文件夹(主要是node_modulewe文件夹),右键选择 ...

  8. WF控制台工作流(2)

    using System; using System.Linq; using System.Activities; using System.Activities.Statements; namesp ...

  9. luogu P3191 [HNOI2007]紧急疏散EVACUATE

    传送门 qwq这题好大力 首先可以预处理出每个人到每个门前面那个格子的最早时间,然后答案如果比最小答案大的话也是合法的,所以可以二分最终答案.检查\(mid\)是否合法就考虑每个人要去哪个门才会合法, ...

  10. B. Light It Up

    题目链接:http://codeforces.com/problemset/problem/1000/B 代码: #include<iostream> #include<cstrin ...