从头开始写框架(一):浅谈JS模块化发展
博客申请下来已经过去一个月了,一直不知道写点什么,毕竟我的文笔不是很好orz。
不过既然申请下来了,不写点什么总是觉得很可惜。正好最近在自己写框架,就把自己的进程和一些心得体会分享出来吧。
写在前面:
这一系列<从头开始写框架>文章,算是我的经验总结。因为以前读各位大牛的源代码时,总是会冒出这样的想法“如果他能把每一步都标注的很明确,那该多好,一定会省下我很多时间。”。但是大牛们愿意分享出源代码已经是很感谢了,怎么还能要求别人这么多呢~ 所以在这系列文章里,会事无巨细的把所有细节都标注清楚。方便后来者参阅的时候能够清楚明晰的了解每一行代码的意图,加深自己的理解。
下面是正文:
为什么要先从模块化的发展谈起呢?这是为了让新手更容易的理解后面的代码意图:为什么有些看起来很简单的事情要花2倍甚至3倍的时间去完成,以及,多花费的时间对我们有何帮助? 让我们带着这些问题来展开本篇文章。
说起JS模块化的发展,我们先从什么是模块化开始说起
很多前端新人刚入行时,写的代码是这样的:
window.onload=function(){ var a = 1;
var b = 2; var oBtn=document.getElementById("btn"); oBtn.onclick=function(){ alert(a+b) // 输出3 }
}
完全面向过程的写法与大量的全局变量。
这样写的好处有什么?也不能说完全没有吧,唯一的好处就是快。想到哪些到哪 ,不用花时间去想代码结构之类的复杂的事情,用来赶工还挺不错的对吧?:-D
但是如果说到坏处,就太多了。随处可见的全局变量导致写着写着某一行就突然报错了,回去检查发现是因为某个变量被修改导致报错。想改已经来不及了,因为太多地方依赖于这个变量,牵一发而动全身。
同时也会给一起合作的伙伴带来麻烦,因为不敢随意修改,所以只能在下面添加新的全局变量来编写业务,但是因为全局变量泛滥,变量与函数同名的事情时有发生。
更不用说因为面向过程的编写方式,导致可重用性几乎为零,维护的时候想要改某个小地方时却发现因为太多的代码依赖于这个地方而无法轻易改动等等各种问题。
那么为了解决这些问题怎么办呢?
我们进化到了函数封装的阶段。
这个阶段,我们的代码是这样的:
function addition(num1,num2){
return num1+num2;
}
function Subtraction(num1,num2){
return num1-num2;
}
window.onload=function(){
alert(addition(1,2));//输出3
alert(Subtraction(2,2))//输出0
}
恩,好一点了。至少可以做到复用了。而且减少了很多全局变量。
然而实际工作中,我们的页面往往是这样的:
<!DOCTYPE html>
<html>
<head>
<title>demo</title>
<script src="....js"></script>
<script src="....js"></script>
<script src="....js"></script>
<script src="....js"></script>
<script src="....js"></script>
<script src="....js"></script>
<script src="....js"></script>
<script src="....js"></script>
</head>
<body> <!--......--> </body>
</html>
因为方便分工,导致了大量的JS文件引入。而封装的函数本质上也是全局对象window的方法,所以还是会发生同名函数的冲突等一系列问题。
而对于动辄就是几千上万行代码的大型项目,显然这样做还是不够安全。
为了解决这个问题,我们开始接触到原型,利用prototype来编写构造器函数的方式。这也是我们初次大范围运用OOP的编程思维,而我们也第一次接触到了设计模式:“构造器模式”
这个时期我们的代码是这样的:
function Calculation(){
this.a;
this.b;
}
Calculation.prototype.init=function(num1,num2){
this.a=num1;
this.b=num2;
}
Calculation.prototype.add=function(){
return this.a+this.b;
}
Calculation.prototype.remove=function(){
return this.a-this.b;
} var cal = new Calculation();
cal.init(2,2) alert(cal.add())//输出4
alert(cal.remove())//输出0
恩,看起来已经很好了,解决了大量全局变量的问题,同时复用性也大大提高。
当然,我们一定不会满足于此。可以看到,我们的构造器函数仍然是一个全局函数。仍然有命名冲突的危险。
为了解决这个问题,我们开始利用闭包+对象的方式。
闭包是一个好东西,它的主要作用分两点:1.防止出现大量的全局变量与函数。因为我们可以用一个立即执行的匿名函数来模拟全局作用域,同时又不会污染全局作用域。
而对象的值对也可以有很多种形式:字符串、数字、布尔值、函数! 没错,对象的值对可以用来储存函数,这样的话,我们只需要把代码写成这样:
var Calculator=(function(){ var a = 2;
var b = 2; return {
add:function(){
return a+b;
},
subtract:function(){
return a-b;
},
}
})() alert(Calculator.add()) //输出4
alert(Calculator.subtract()) //输出0
首先这里的a和b两个变量因为写在了匿名函数里,所以变成了两个局部变量。这样做的好处是,外部无法修改它们。它们是两个只读属性,这样做就避免了因为修改它们而导致的出错。
恩,看起来已经很安全了。但是这样真的就安全了么?
让我们来看看Calculator这个变量,它本质上是一个返回的对象,而对象的键值对都是可以被修改的。这也就导致有可能会有其他人也同时使用这个名称定义了一个对象,而误修改了它的属性。而这是我们一定不允许发生的!
而且我们的工作方式实际上好像并没有什么变化:仍然是每人定义一个全局对象,然后各写各的,期盼着不要遇到上述问题。这样带来的问题仍然是:不利于分工合作。
相信到这里,你已经非常明白,为什么看起来如此简单的a+b,我们需要“大费周章”的绕这么多的弯去解决它,已经这可以为我们带来怎样的好处。
那么,让我们来想一下,如果我们可以把所有的代码分成一个个模块,在我们需要时,去引用它,不需要时,它也不会对其它部分产生任何影响。
听起来很美好不是么?恩,下一章节我们就来着手实现它。
从头开始写框架(一):浅谈JS模块化发展的更多相关文章
- 浅谈JS中的闭包
浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...
- 浅谈 js 正则字面量 与 new RegExp 执行效率
原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...
- 浅谈 js 正则之 test 方法
原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...
- 浅谈 js 数字格式类型
原文:浅谈 js 数字格式类型 很多人也许只知道 ,123.456,0xff 之类的数字格式.其实 js 格式还有很多数字格式类型,比如 1., .1 这样的,也有 .1e2 这样的. 可能有人说这是 ...
- 浅谈 js 语句块与标签
原文:浅谈 js 语句块与标签 语句块是什么?其实就是用 {} 包裹的一些js代码而已,当然语句块不能独立作用域.可以详细参见这里<MDN block> 也许很多人第一印象 {} 不是对象 ...
- 浅谈 js 字符串 trim 方法之正则篇
原文:浅谈 js 字符串 trim 方法之正则篇 关于 trim 其实没啥好说的,无非就是去除首位空格,对于现代浏览器来说只是简单的正则 /^\s+|\s+$/ 就可以搞定了.而且支持中文空格 等 ...
- 浅谈JS严格模式
浅谈JS严格模式 简介 何为严格模式?严格模式(strict mode)即在严格的条件下运行,在严格模式下,很多正常情况下不会报错的问题语句,将会报错并阻止运行. 但是,严格模式可以显著提高代码的健壮 ...
- 浅谈JS中的!=、== 、!==、===的用法和区别 JS中Null与Undefined的区别 读取XML文件 获取路径的方式 C#中Cookie,Session,Application的用法与区别? c#反射 抽象工厂
浅谈JS中的!=.== .!==.===的用法和区别 var num = 1; var str = '1'; var test = 1; test == num //tr ...
- 浅谈JS中 var let const 变量声明
浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...
随机推荐
- 【poj3709】 K-Anonymous Sequence
http://poj.org/problem?id=3709 (题目链接) 题意 给出一个n个数的序列,要求将其中一些数改为另一个比它小的数,改动的花费为两数的绝对值,完成改动后使得整个序列中出现过的 ...
- Android成长日记-使用ViewFlipper实现屏幕切换动画效果
(一) ViewFlipper介绍 Android系统自带的一个多页面管理控件,它可以实现子界面的自动切换 (二) 为ViewFlipper加入View 1. 静态导入:在Layout布局文件中直接导 ...
- TCP/IP详解 笔记十四
TCP/IP协议(二) 连接的建立与终止 tcpdump -S输出TCP报文的格式 格式: 源>目的:标志 (标志就是tcp头部).标识首字符意义如下: 例如:telnet 某服务的输出(包括 ...
- 第一个python程序-判断登陆用户名和密码是否正确
#setencoding=utf-8 #用户名和密码输入正确,则登陆成功 #用户名正确密码错误,只再输入密码,有3次机会 #错误3次,则把用户名放入lock中 import os,sys #存放用户名 ...
- oracle修改表字段名时报错:ORA-00054:资源正忙,但指定以NOWAIT方式获取资源,或者超时失效的问题
打开sql plus select session_id from v$locked_object;查询出oracle锁定的会话ID SELECT sid, serial#, username, os ...
- BZOJ1798: [Ahoi2009]Seq 维护序列seq
传送门 写这道题是为了get一个同时传送乘法下标和加法下标的小技巧,线段树模板题.不多说. 标记名字打错无限智力-- //BZOJ 1798 //by Cydiater //2016.9.13 #in ...
- json的解释
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.JSON采用完全独立于语言的文本格式,这些特性使JSON成为理想的数据交换语言.易于人阅读和编写,同时也易 ...
- bigdecimal类型数据的min方法
java.math.BigDecimal.min(BigDecimal val) 返回此BigDecimal和val的最小值. 声明 以下是java.math.BigDecimal.min()方法的声 ...
- android语音识别和合成第三方 .
讯飞语音云 http://open.voicecloud.cn/index.php 目前支持6大类型的SDK下载,包括Android. iPhone平台移动应用的接入,Windows.Linux平台P ...
- Linux查看CPU和内存使用情况
在系统维护的过程中,随时可能有需要查看 CPU 使用率,并根据相应信息分析系统状况的需要.在 CentOS 中,可以通过 top 命令来查看 CPU 使用状况.运行 top 命令后,CPU 使用状态会 ...