预备知识
闭包
- 闭包最常用的方式就是返回一个内联函数(内联函数就是函数内部声明的函数)。
- 在JS中有作用域和执行环境的问题,在函数内部的变量在函数外部是无法访问的,在函数内部却可以得到全局变量。由于各种原因,我们有时需要得到函数内部的变量,这时就可以创建一个闭包,用来在函数外部访问这个变量。
- 闭包的用途:主要就是读取函数内部变量,还有一个作用是使这些变量可以一直保存在内存中。
- 使用闭包要注意:由于变量被保存在内存中,所以会对内存造成消耗,所以不要滥用闭包。解决方法:在退出函数之前,将不使用的局部变量全部删除。
封装
- 通过将一个方法或者属性声明为私用的,可以让对象的实现细节对其他对象保密以降低对象之间的耦合程度,可以保持数据的完整性并对其修改方式加以约束,使代码更可靠并易于调试。封装是面向对象设计的基石。
- 尽管js是面向对象的语言,但是它不具备将成员声明为公用或私用的任何内部机制。
- 私有属性和方法:函数有作用域,在函数内用var关键字声明的变量在外部无法访问。
- 特权属性和方法:创建属性和方法时使用的this关键字,因为这些方法定义在构造器的作用域中,所以它们可以访问到私有属性和方法。只有那些需要直接访问私有成员的方法才应该被设计为特权方法。
- 共有属性和方法:直接连在prototype上的属性和方法,不可以访问构造器内的私有成员,可以访问特权成员,子类汇集成所有的共有方法。
- 共有静态属性和方法:可以将其想象成一个命名空间,实际上相当于把构造器作为命名空间来使用。
var _func = function() {
var name = 'Xiao';
var method = function(){}
this.page = 'one';
this.getName = function(){return name}
}
_func._title = 'Learning';
_func.sayTitle = function(){console.log(_func._title)}
_func.prototype = {
init: function(){},
start: function(){}
}
继承
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
}
var a = new Person('xiao');
alert(a.getName());
function Pro(name, age){
Person.call(this, name);
this.age = age;
}
Pro.prototype = new Person();
Pro.prototype.constructor = Pro;
Pro.prototype.getAge = function(){
return this.age;
}
var b = new Pro('sun', 22);
javascript设计模式
- 单体模式、工厂模式、桥梁模式,对抽象编程和接口编程都非常有好处
- 装饰者模式和组合模式很多相似:它们都与所包装的对象实现同样的接口并且会把人和方法的调用传递给这些对象。
- 门面模式,几乎所有的js库都会用到这个模式;配置器模式和门面模式相似
- 享元模式:是一种以优化为目的的模式
- 代理模式:主要用于控制对象的访问,包括推迟对其创建需要耗用大量计算资源的类得实例化
- 观察者模式:用于对对象的状态进行观察,并且当它发生变化时得到通知的方法。用于让对象对事件进行监听以便对其作出相应。观察者模式也叫订阅者模式。
- 命令模式:是对方法调用进行封装的方式,用命令模式可以对方法调用进行参数化和传递,然后在需要的时候再加以执行
- 指责链模式:用来消除请求的发送者和接受者之间的耦合
单体模式
- 单体模式:用来划分命名空间,减少网页中全局变量的个数。
var funs = {
name: 'xiao',
getName: function(){},
init: function(){},
start: function(){}
}
工厂模式
- 工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
- 工厂就是把成员对象的创建工作转交给一个外部对象,好处在于消除对象之间的耦合(何为耦合?就是相互影响)。通过使用工厂方法而不是new关键字及具体类,可以把所有实例化的代码都集中在一个位置,有助于创建模块化的代码,这才是工厂模式的目的和优势。
var XMLHttpFactory = function(){};
XMLHttpFactory.createXMLHttp = function(){
var XMLHttp = null;
if(window.XMLHttpRequest){
XMLHttp = new XMLHttpRequest();
} else if(window.ActiveXObject){
XMLHttp = new ActiveXObject('Microsoft.XMLHTTP')
}
return XMLHttp;
}
var AjaxHander = function(){
var XMLHttp = XMLHttpFactory.createXMLHttp();
}
- 工厂模式:氛围简单工厂模式和抽象工厂模式
- 抽象工厂模式的使用方法:先设计一个抽象类,这个类不能被实例化,只能用来派生子类,最后通过对子类的扩展实现工厂模式。
桥接模式
- 桥接模式:可以用来弱化它与使用它的类核对象之间的耦合
- 桥接模式最常见的应用场合:事件监听器回掉函数
装饰者模式
组合模式
- 将对象组合成树形结构以表示“部分-整体”的层次结构,它使得客户对单个对象和复合对象的使用具有一致性
- 组合模式就是将一系列相似或相近的对象组合在一个大的对象,由这个大对象提供一些常用的借口来对这些小对象进行操作,代码可充用,对外操作简单。
门面模式
- 门面模式是几乎所有js库的核心原则
- 两个作用:简化类的接口;消除类与使用它的客户代码之间的耦合
- 门面模式的使用目的就是图方便
- 其实桌面上的快捷方式图标就在扮演一个把用户引导至某个地方的接口的角色
适配器模式
代理模式
- 代理模式:最基本的形式是对访问进行控制。
- 代理对象和另一个对象(本体)实现的是同样的接口,可是实际上工作还是本体在做,它才是负责执行所分派的任务的那个对象或类,代理对象不会再另一对象的基础上修改人和方法,也不会简化那个对象的接口
观察者模式
- 观察者模式:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
- 观察者模式中两的角色:观察者、被观察者
- 事件监听器说到底就是一种内置的观察者
- 事件处理器(handler)与事件监听器(listener)不是一回事,前者就是一种把事件传给与其关联的函数的手段,后者,一个事件可以与几个监听器关联,每个监听器都能独立于其他监听器而改变。
- 借助一个事件监听器替你处理各种行为,从而降低内存消耗和提高互动性能
命令模式
- 命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作
职责链模式
- 职责链模式:为清除请求的发送者和接受者之间耦合,而使多个对象都有机会处理这个请求。