标签:地方 匿名 actor rip user color 输出 引用类型 img
今天收获比较多,仿佛无意中打通了七筋八脉,想通了一些原理性的东西。对js有了更深的理解。
首先说说闭包,闭包在我们实际开发中处处被用到,那个它到底是个什么东西呢?
var user=(function(){ var USER={ name:"mapleTao", password:"123456" } return { getName:function(){ return USER.name; }, getPassword:function(){ return USER.password; } } })(); console.log(user.getName()) console.log(user.getPassword()) console.log(USER)
上面就是一个简单的闭包,输出结果为mapleTao,123456,error;让我们先来解析下这个例子干了什么,我们先声明了一个叫user的变量,后面是一个闭包,闭包分成两部分,一部分是前面的匿名函数,后面是该函数的调用,简单点说就是立即执行了这个函数并返回一个对象。对象中包括了两个获取值的方法。在js中是没又常量这也说法的,但是呢,因为js是一门比较灵活的语言,所以呢我们通过闭包就创建了一个这样的“常量”,上面的例子只提供给你获取值的方法,但是呢,你并不能修改USER的内容,这个像不像java中的常量呢?
变量又两种,一种是全局变量,一种是局部变量,我们都知道全局变量是在所有的地方都能访问到,这是比较危险的,因为所有人都能修改它,它的作用域太大了。还有一种是局部变量,顾名思义,局部变量就是一个小区域的变量,我们能在函数内部找到它,但是在外面你是找不到它的。闭包就可以做到让我们在函数外部访问到函数内部的变量。
闭包的好处:
1:不会污染全局变量。上面这个例子中是无法直接访问到user的
2:让一个变量永久保存到内存中,不会被回收系统回收掉。我们能通过它提供的方法访问到它,说明它是保存到内存中的而且也没有被清掉
3:创建立即执行。
4:形成一个独立的作用域。上面这个例子中,匿名函数内部就是一个独立的作用域,这个作用域里面的变量外部无法直接获取。
缺点
1:占内存。因为它不会被gc回收,所以会占内存空间,严重可能会导致内存泄漏。
2:外部可以改变内部函数的值。
接下来聊聊构造函数,js中虽没有类的说法,但是呢我们可以通过不同的方法来让它实现这个效果。不多说上代码。
function Book(name,type,author){ if(this instanceof Book){ this.name=name; this.type=type; this.author=author; }else{ return new Book(name,type,author); } }; Book.prototype={ introduce:function(){ console.log(this.name+"--"+this.type+"--"+this.author); } }; var HTML=new Book("h5开发","Book","maple"); var js=Book("设计模式","Book","tao"); HTML.introduce(); js.introduce();
上面这段代码就是一个简单的构造函数,通过构造函数,生成相似的对象。简单来说构造模式就是用来创建相似对象的函数,也就是对一些相同代码的封装,简单点来说就是优化,将一些重复使用的代码抽象出来。这个可以减少代码量,增加代码的复用性。
上面这个构造函数也用到了原型模式,原型模式在我看来也是一种优化,因为对象的原型是一个引用类型,引用类型比较特殊,它是指向堆的,所以不会重复分配内存,可以减少内存的占用率,而且prototype是一个函数自带的属性,写在里面可读性更强。
//报纸 function Newspaper(name,type,author){ if(this instanceof Newspaper){ this.name=name; this.type=type; this.author=author; }else{ return new Newspaper(name,type,author); } }; Newspaper.prototype={ introduce:function(){ console.log(this.name+"--"+this.type+"--"+this.author); } }; //杂志 function Magazine(name,type,author){ if(this instanceof Magazine){ this.name=name; this.type=type; this.author=author; }else{ return new Magazine(name,type,author); } }; Magazine.prototype={ introduce:function(){ console.log(this.name+"--"+this.type+"--"+this.author); } };
上面我们又创建了两个构造函数,一个是报纸构造函数,一个是杂志构造函数,但是如果你交给别人用的话,不可能给对方三个函数,而且在用法方面可能会有点问题,所以这个时候我们的封装一下。提供一个接口。
我们用简单工厂模式封装下以上代码。
var createFactory=function(name,type,author){ var obj; switch(type){ case "Book": obj=new Book(name,type,author); break; case "Newspaper": obj=new Newspaper(name,type,author); break; case "Magazine": obj=new Magazine(name,type,author); break; } return obj; }; var mag=createFactory("剎漫画","Magazine","漫画"); var news=createFactory("新闻","Newspaper","新闻"); var bk=createFactory("一本书","Book","书"); console.log("-------------"); mag.introduce(); news.introduce(); bk.introduce(); console.log("-------------");
上面就是一个简单的工厂模式,createFactory就是一个书店,但我们去买书的时候,就知道告诉它我们买一本杂志或者报纸啊,后面的就交给书店老板解决了。
上面三个函数有很多共同点,这个时候我们可以进一步的优化代码,我们可以把相同的抽象出来来,不同的再判断,如下。
var createBook=function(name,type,author){ var o={}; o.name=name; o.type=type; o.author=author; o.introduce=function(){ console.log(this.name+"--"+this.type+"--"+this.author+"--"+this.status); } if(type==="Book"){ o.status=0; } if(type==="Magazine"){ o.status=1; } if(type ==="Newspaper"){ o.status=2; } return o; } var mag1=createBook("剎漫画","Magazine","漫画"); var news1=createBook("新闻","Newspaper","新闻"); var bk1=createBook("一本书","Book","书"); mag1.introduce(); news1.introduce(); bk1.introduce();
但是,从上面这段代码来看,但对象很多时会特别复杂,很难维护,而且introuce每次都会去实例一次,所以还可以想办法再优化下。
今天就先到这里,咋先去休息下。更多精彩请听下回分解。
标签:地方 匿名 actor rip user color 输出 引用类型 img
原文地址:http://www.cnblogs.com/mapletao/p/6067937.html