从头开始写框架(一):浅谈JS模块化发展

博客申请下来已通过去一个月了,一直不知道写点什么,毕竟个人文笔不是很好orz。html

不过既然申请下来了,不写点什么老是以为很惋惜。正好最近在本身写框架,就把本身的进程和一些心得体会分享出来吧。前端

 

写在前面:编程

这一系列<从头开始写框架>文章,算是个人经验总结。由于之前读各位大牛的源代码时,老是会冒出这样的想法“若是他能把每一步都标注的很明确,那该多好,必定会省下我不少时间。”。可是大牛们愿意分享出源代码已是很感谢了,怎么还能要求别人这么多呢~  因此在这系列文章里,会事无巨细的把全部细节都标注清楚。方便后来者参阅的时候可以清楚明晰的了解每一行代码的意图,加深本身的理解。设计模式

 

下面是正文:安全

为何要先从模块化的发展谈起呢?这是为了让新手更容易的理解后面的代码意图:为何有些看起来很简单的事情要花2倍甚至3倍的时间去完成,以及,多花费的时间对咱们有何帮助? 让咱们带着这些问题来展开本篇文章。闭包

 

提及JS模块化的发展,咱们先从什么是模块化开始提及框架

不少前端新人刚入行时,写的代码是这样的:模块化

 

window.onload=function(){


var a = 1;
var b = 2;

var oBtn=document.getElementById("btn"); oBtn.onclick=function(){   alert(a+b) // 输出3
} }

 

 

彻底面向过程的写法与大量的全局变量。函数

这样写的好处有什么?也不能说彻底没有吧,惟一的好处就是快。想到哪些到哪 ,不用花时间去想代码结构之类的复杂的事情,用来赶工还挺不错的对吧?:-Dthis

可是若是说到坏处,就太多了。随处可见的全局变量致使写着写着某一行就忽然报错了,回去检查发现是由于某个变量被修改致使报错。想改已经来不及了,由于太多地方依赖于这个变量,牵一发而动全身。

同时也会给一块儿合做的伙伴带来麻烦,由于不敢随意修改,因此只能在下面添加新的全局变量来编写业务,可是由于全局变量泛滥,变量与函数同名的事情时有发生。 

更不用说由于面向过程的编写方式,致使可重用性几乎为零,维护的时候想要改某个小地方时却发现由于太多的代码依赖于这个地方而没法轻易改动等等各类问题。

 

那么为了解决这些问题怎么办呢?

咱们进化到了函数封装的阶段。

这个阶段,咱们的代码是这样的:

 
 
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,咱们须要“大费周章”的绕这么多的弯去解决它,已经这能够为咱们带来怎样的好处。

 

那么,让咱们来想一下,若是咱们能够把全部的代码分红一个个模块,在咱们须要时,去引用它,不须要时,它也不会对其它部分产生任何影响。

听起来很美好不是么?恩,下一章节咱们就来着手实现它。

相关文章
相关标签/搜索