组合模式
组合模式就是用小的子对象来构建更大的对象,而这些小的子对象本身也许是由更小的”孙对象”构成的。
一、回顾宏命令宏命令对象包含了一组具体的子命令对象,不管是宏命令对象,还是子命令对象,都有一个execute方法负责执行命令。
var closeDoorCommand = { execute: function(){ console.log('关门'); }};var openPcCommand = { execute: function(){ console.log('开电脑'); }};var openQQCommand = { execute: function(){ console.log('登录QQ'); }};var MacroCommand = function(){ return { ...
命令模式
假设有一个快餐店,而我是快餐店的点餐服务员,那么我一天的工作应该是这样的:当某位客人点餐或者打来订餐电话后,我会把他的需求都写在清单上,然后交给厨房,客人不用关心的是哪些厨师帮他炒菜。我们餐厅还可以满足客人需要的定时服务,比如客人正在回家的路上,要求1个小时后才开始炒他的菜,只要订单还在,厨师就不会忘记。客人也可以很方便地打电话来撤销订单。另外如果有太多地客人点餐,厨房可以按照订单的顺序排队炒菜。
这些记录着订餐信息的清单,便是命令模式中的命令对象。
一、命令模式的用途命令模式是最简单和优雅的模式之一,命令模式中的命令(command)指的是一个执行某些特定事情的指令。
命令模式最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。
拿订餐来说,客人需要向厨师发送请求,但是完全不知道这些厨师的名字和联系方式,也不知道厨师炒菜的方式和步骤。命令模式把客人订餐的请求封装成command对象,也就是订餐中的订餐对象。这个对象可以在程序中被四处传递, ...
发布-订阅模式
发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。在JavaScript开发中,我们一般用事件模型来替代传统的发布-订阅模式。
一、现实中的发布-订阅模式小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄。好在售楼MM告诉小明,不久之后还有一些尾盘推出,开发商正在办理相关手续,手续办好后便可以购买。但到底是什么时候,目前还没有人能够知道。
于是小明记下了售楼处的电话,以后每天都会打电话过去询问是不是已经到了购买时间。除了小明,还有小红、小强、小龙也会每天向售楼处咨询这个问题。一个星期过后,售楼MM决定辞职,因为厌倦了每天回答1000个相同内容的电话。
当然现实中没有那么笨的销售公司,实际上故事是这样的:小明离开之前,把电话号码留在了售楼处。售楼MM答应他,新楼盘一推出就马上发信息给小明。小红、小强、小龙也是一样,他们的电话号码都被记在售楼处的花名册上,新楼盘退出的时候,售楼MM会翻开花名册,遍历上面的电话号码,依次发送一条短信来通知他们。
二、发布-订阅模式的作用在这个例子中使用发布-订阅模式 ...
迭代器模式
看本文之前需要有JavaScript的基础知识
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。
一、实现自己的迭代器实现一个each函数,each函数接受2个参数,第一个为被循环的数组,第二个为循环中的每一步后将被触发的回调函数:
var each = function(ary,callback){ for(var i = 0, l = ary.length; i < l; i++){ callback.call(ary[i], i, ary[ i ]); // 把下标和元素当作参数传给callback函数 }};each([1, 2, 3], function(i, n){ alert([i, n]);});
二、内部迭代器和外部迭代器迭代器可以分为内部迭代器和外部迭代器
内部迭代器我们刚刚编写的ea ...
代理模式
看本文之前需要有JavaScript的基础知识
代理模式是为了一个对象提供一个代用品或占位符,以便控制对它的访问
道理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象。替身对象对请求做出一些处理后,再把请求转交给本体对象。
一、第一个例子——小明追MM的故事
在四月一个晴朗的早晨,小明遇到了他百分百女孩,我们暂且称呼小明的女神为A。两天过后,小明决定给A送一束花来表白。刚好小明打听到A和他有一个共同的朋友B,于是内向的小明决定让B来代替自己完成送花这件事情。
不用代理模式:
var Flower = function(){};var xiaoming = { sendFlower: function(target){ var flower = new Flower(); target.receiveFlower(flower); }};var A = { receiveFlower: f ...
单例模式
看本文之前需要有JavaScript的基础知识
单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
一、实现单例模式用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。
var Singleton = function(name){ this.name = name;};Singleton.prototype.getName = function(){ alert(this.name);};Singleton.getInstance = (function(){ var instance = null; return function(name){ if(!instance){ instance = new Singleton(name); } return instance; }})();var a = Singl ...
策略模式
看本文之前需要有JavaScript的基础知识
策略模式的定义是:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。
一、使用策略模式计算奖金
最初代码实现:var calculateBonus = function(performanceLevel, salary){ if(performanceLevel === 'S'){ return salary * 4; } if(performanceLevel === 'A'){ return salary * 3; } if(performanceLevel === 'B'){ return salary * 2; }};calculateBonus('B',20000); // 40000calculateBonus('S',6000); // 24000 ...
闭包和高阶函数
看本文之前需要有JavaScript的基础知识
一、闭包
变量的作用域当在函数中声明一个变量的时候,如果该变量前面没有带上关键字 var ,这个变量就会成为全局变量。另一种情况是用 var 关键字在函数中声明变量,这时候变量即是局部变量。
在JavaScript中,函数可以用来创造函数作用域,此时的函数就像一层半透明的玻璃,在函数里面可以看到外面的变量,而在函数外面无法看到函数里面的变量。这是因为当在函数中搜索一个变量的时候,如果该函数内并没有声明这个变量,那么此次搜索的过程会随着代码执行环境创建的作用域链往外层逐层搜索,一直搜索到全局对象为止。变量的搜索是从内到外而非从外到内的。
var a = 1;var func1 = function(){ var b = 2; var func2 = function(){ var c = 3; alert(b); // 2 alert(a); // 1 } func2(); alert(c); // c is not ...
this、call和apply
一、thisthis的四种绑定方式:隐式绑定、显式绑定、window绑定、new绑定
隐式绑定:使用对象来调用其内部的一个方法,该方法的this是指向对象本身的,this永远指向最后调用它的那个对象。
显式绑定:通过call来设置函数执行上下文的this指向。
window绑定:在ES5严格模式中,JavaScript不会默认this指向window对象,而会正确地把this保持为underfined。
new绑定:用new调用函数时,JavaScript解释器都会在底层创建一个全新地对象并把这个对象当做this
改变this指向:
使用ES6箭头函数
在函数内部使用_this = this
使用apply、call、bind
new一个实例化对象
this的指向
作为对象方法调用当函数作为对象地方法被调用时,this指向该对象
var obj = { a: 1, getA: function(){ alert(this === obj); // true alert(this.a); ...
面向对象的JavaScript
看本文之前需要有JavaScript的基础知识
JavaScript没有提供传统面向对象语言中的类式继承,而是通过原型委托的方式来实现对象与对象之间的继承,也没有在语言层面提供对抽象类和接口的支持
一、动态类型语言和鸭子模型编程语言按照数据类型大体可分为两类:静态类型语言、动态类型语言
静态类型语言在编译时便已经确定变量的类型,而动态类型语言的变量类型要到程序运行的时候,待变量被赋予某个值后,才会具有某种类型。
静态语言
优点:
在编译时就能发现类型不匹配的错误,如果在程序中明确规定了数据类型,编译器还可以针对这些信息对程序进行一些优化的工作,提高程序执行速度
缺点:
迫使程序员按照锲约来编写程序,类型的声明会增加更多代码
动态语言
优点:
编写的代码数量少,更加简洁
缺点:
无法保证变量的类型,从而在程序的运行期有可能发生跟类型相关的错误
在JavaScript中,当我们对一个变量赋值时,虽然不需要考虑他的类型,因此,JavaScript是一门典型的动态类型语言。
这一切都建立在鸭子类型的概念上,鸭子类型的通俗说法是:”如果它走起路来像鸭子,叫起来也像鸭子, ...