├── chapter_05 ├── 5.1抽象类 ├── README.md └── 5.2抽象工厂模式.js ├── chapter_07 ├── README.md ├── 7.5原型继承.js ├── 7.2创建一个焦点图.js └── 7.3最优的解决方案.js ├── chapter_03 ├── README.md ├── 3.3一个对象有时候也可代替许多类_1.js ├── 3.3使用工厂模式改进需求_2.js ├── 3.1工作中的第一次需求.js └── 3.2如果类太多,那么提供一个.js ├── chapter_11 ├── README.md ├── 11.3站长统计.js └── 11.4JSONP.html ├── chapter_08 ├── README.md ├── 8.5无法修改的静态变量.js └── 8.6惰性单例.js ├── chapter_10 ├── README.md ├── 10.7服务器端数据适配.js ├── 10.5参数适配器.js ├── 10.6数据适配.js └── 10.4适配异类框架.js ├── chapter_09 ├── README.md ├── 9.2兼容方式.js ├── 9.3除此之外.js └── 9.4小型代码库.js ├── README.md ├── chapter_01 ├── 1.1.入职第一天.js ├── 1.2函数的另一种形式.js ├── 1.3用对象收编变量.js ├── 1.4对象的另一种形式.js ├── 1.6类也可以.js ├── 1.5真假对象.js ├── 1.11换一种方式使用方法.js ├── 1.10可以链式添加吗.js ├── 1.7一个检测类.js ├── 1.8方法还可以这样用.js └── 1.9函数的祖先.js ├── chapter_06 ├── README.md └── 6.2创建对象的另一种形式.js ├── chapter_02 ├── 2.2.1创建一个类.js ├── 2.5多态_1.js ├── 2.3.5寄生式继承.js ├── 2.3.1类式继承_2.js ├── 2.3.1类式继承_1.js ├── 2.3.2构造函数继承.js ├── 2.5多态_2.js ├── 2.4.1单继承.js ├── 2.2.3闭包的实现_1.js ├── 2.3.4原型式继承.js ├── 2.2.3闭包的实现_2.js ├── 2.2.2属性与方法的封装.js ├── 2.4.2多继承.js ├── 2.2.4创建对象的安全模式.js ├── 2.3.3组合继承.js └── 2.3.6寄生组合式继承.js └── chapter_04 ├── 4.3安全模式类.js ├── 4.1广告展现.js └── 4.4安全的工厂方法.js /chapter_05/5.1抽象类: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter_07/README.md: -------------------------------------------------------------------------------- 1 | ###原型模式 2 | 用原型实例指向创建对象的类,适用于创建新的对象的类共享原型对象的属性基方法。 3 | -------------------------------------------------------------------------------- /chapter_03/README.md: -------------------------------------------------------------------------------- 1 | ###简单工厂模式 2 | 又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象。 3 | -------------------------------------------------------------------------------- /chapter_11/README.md: -------------------------------------------------------------------------------- 1 | ###代理模式 2 | 由于一个对象不能直接饮用另一个对象,所以需要通过代理对象在这两个对象之间起到中介作用。 3 | -------------------------------------------------------------------------------- /chapter_08/README.md: -------------------------------------------------------------------------------- 1 | ###单例模式 2 | 又被称为单体模式,是只允许实例化一次的对象类。有时候我们也用一个对象来规划一个命名空间,并井井有条的管理对象的属性与方法。 3 | -------------------------------------------------------------------------------- /chapter_10/README.md: -------------------------------------------------------------------------------- 1 | ###适配器模式 2 | 将一个类(对象)的接口(方法或者属性)转化成另一个接口,以满足用户的需求,使类(对象)之间接口的不兼容问题通过适配器得意解决。 3 | -------------------------------------------------------------------------------- /chapter_09/README.md: -------------------------------------------------------------------------------- 1 | ###外观模式 2 | 为一组复杂的子系统接口提够一个更高级的统一接口,通过这个接口是的对子系统接口的访问更容易,在JavaScript中有时候也会用于对底层接口兼容性做统一封装来简化用户使用。 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # javascript-design-patterns02 2 | 《javascript设计模式》--张容铭(源码和学习总结) 3 | 4 | 参考资料:《javascript设计模式》--张容铭 5 | 内容主要包含本书的全部源码,并包含了书内知识点的摘录和总结 6 | -------------------------------------------------------------------------------- /chapter_05/README.md: -------------------------------------------------------------------------------- 1 | ###抽象工厂模式 2 | 通过对类的工厂抽象使其业务用于对产品类簇的创建,而不负责创建某一类产品的实例。 3 | 抽象类中定义的方法只是显性的定义一些功能。但没有具体的实现,而一个对象是要具有一套完整的功能的,所以用抽象类穿件的对象当然也是“抽象”的了,所以我们不能使用它来创建一个真实的对象。 4 | -------------------------------------------------------------------------------- /chapter_01/1.1.入职第一天.js: -------------------------------------------------------------------------------- 1 | function checkName() { 2 | // 验证姓名 3 | } 4 | 5 | function checkEmail() { 6 | // 验证邮箱 7 | } 8 | 9 | function checkPassword() { 10 | // 验证密码 11 | } 12 | -------------------------------------------------------------------------------- /chapter_01/1.2函数的另一种形式.js: -------------------------------------------------------------------------------- 1 | var checkName = function() { 2 | // 验证姓名 3 | }; 4 | 5 | var checkEmail = function() { 6 | // 验证邮箱 7 | }; 8 | 9 | var checkPassword = function() { 10 | // 验证密码 11 | }; 12 | -------------------------------------------------------------------------------- /chapter_01/1.3用对象收编变量.js: -------------------------------------------------------------------------------- 1 | var CheckObject = { 2 | checkName: function() { 3 | // 验证姓名 4 | }, 5 | checkEmail: function() { 6 | // 验证邮箱 7 | }, 8 | checkPassword: function() { 9 | // 验证密码 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /chapter_01/1.4对象的另一种形式.js: -------------------------------------------------------------------------------- 1 | var CheckObject = function() {}; 2 | CheckObject.checkName = function() { 3 | // 验证姓名 4 | }; 5 | CheckObject.checkEmail = function() { 6 | // 验证邮箱 7 | }; 8 | CheckObject.checkPassword = function() { 9 | // 验证密码 10 | }; 11 | -------------------------------------------------------------------------------- /chapter_01/1.6类也可以.js: -------------------------------------------------------------------------------- 1 | var CheckObject = function() { 2 | this.checkName = function() { 3 | // 验证姓名 4 | }; 5 | this.checkEmail = function() { 6 | // 验证邮箱 7 | }; 8 | this.checkPassword = function() { 9 | // 验证密码 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /chapter_01/1.5真假对象.js: -------------------------------------------------------------------------------- 1 | var CheckObject = function() { 2 | return { 3 | checkName: function() { 4 | // 验证姓名 5 | }, 6 | checkEmail: function() { 7 | // 验证密码 8 | }, 9 | checkPassword: function() { 10 | // 验证密码 11 | } 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /chapter_06/README.md: -------------------------------------------------------------------------------- 1 | ###建造者模式 2 | 将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可采用不同的表示。 3 | 4 | ###建造者模式与工厂模式的区别 5 | 工厂模式主要是为了创建对象实例或者类簇(抽象工厂),关心的是最终产出(创建)的是什么。不关心你创建的整个过程,仅仅需要知道你最终创建的结果。所以通过工厂模式我们得到的都是对象实例或者族类。然而建造者模式在创建对象是要更为复杂一些,虽然其目的也是为了创建对象,但是他更多关心的是穿件这个对象的整个过程,甚至于创建对象的每一个细节。 6 | 7 | 以前工厂模式创建出来的是一个对象,他追求的是创建的结果,别无他求,所以那仅仅是一个实实在在的创建过程,而建造者模式就有所不同,他不仅仅可以得到创建的结果,而且也参与了创建的具体过程,对于创建的具体实现的细节也参与了干涉,所以说创建的对象更复杂,或者说这种模式创建的对象是一个复合对象。 8 | -------------------------------------------------------------------------------- /chapter_08/8.5无法修改的静态变量.js: -------------------------------------------------------------------------------- 1 | var Conf = (function() { 2 | // 私有变量 3 | var conf = { 4 | MAX_NUM: 100, 5 | MIN_NUM: 1, 6 | COUNT: 1000 7 | }; 8 | // 返回取值器对象 9 | return { 10 | // 取值器方法 11 | get: function(name){ 12 | return conf[name] ? conf[name] : null; 13 | } 14 | }; 15 | })(); 16 | 17 | var count = Conf.get("COUNT"); 18 | console.log(count); // 1000 19 | -------------------------------------------------------------------------------- /chapter_01/1.11换一种方式使用方法.js: -------------------------------------------------------------------------------- 1 | Function.prototype.addMethod = function(name, fn) { 2 | this.prototype[name] = fn; 3 | return this; 4 | }; 5 | 6 | // 此时我们还可以按照上一种方式添加方法 7 | var Methods = function() {}; 8 | Methods.addMethod("checkName", function() { 9 | // 验证姓名 10 | }).addMethod("checkEmail", function() { 11 | // 验证邮箱 12 | }); 13 | 14 | // 但是我们现在使用的时候需要注意了,不能直接使用,要通过new关键字来创建新对象想。 15 | var m = new Methods(); 16 | m.checkEmail(); 17 | -------------------------------------------------------------------------------- /chapter_10/10.7服务器端数据适配.js: -------------------------------------------------------------------------------- 1 | /** 使用适配器模式将后端返回的数据格式化为理想的数据格式 */ 2 | 3 | // 理想的数据格式是一个一维数组 4 | function ajaxAdapter(data) { 5 | // 处理数据并返回新数据 6 | return [data["key1"], data["key2"], data["key3"]]; 7 | } 8 | 9 | $.ajax({ 10 | url: "someAdress.php", 11 | success: function(data, status) { 12 | if (data) { 13 | // 使用适配后的数据--返回的对象 14 | doSomething(ajaxAdapter(data)); 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /chapter_10/10.5参数适配器.js: -------------------------------------------------------------------------------- 1 | /** 应用适配器模式来为函数提供默认参数,以保证函数传参的完整性 */ 2 | function doSomeThing(obj) { 3 | var _adapter = { 4 | name: "雨夜清河", 5 | title: "设计模式", 6 | age: 24, 7 | color: "pink", 8 | size: 100, 9 | prize: 50 10 | }; 11 | for (var variable in _adapter) { 12 | _adapter[i] = obj[i] || _adapter[i]; 13 | } 14 | // 或者 extend(_adapter, obj) 注:此时可能会多添加属性 15 | // do things 16 | } 17 | -------------------------------------------------------------------------------- /chapter_11/11.3站长统计.js: -------------------------------------------------------------------------------- 1 | // 统计代理 2 | var Count = (function(){ 3 | // 缓存图片 4 | var img= new Image(); 5 | // 返回统计函数 6 | return function(param){ 7 | // 统计请求字符串 8 | var str = "http://www.count.com/a.gif?"; 9 | // 拼接请求字符串 10 | for(var i in param){ 11 | str += i + "=" + param[i]; 12 | } 13 | // 发送统计请求 14 | img.src = str; 15 | }; 16 | })(); 17 | 18 | // 测试用例:统计num 19 | Count({num: 10}); 20 | -------------------------------------------------------------------------------- /chapter_02/2.2.1创建一个类.js: -------------------------------------------------------------------------------- 1 | var Book = function(id, bookname, price) { 2 | this.id = id; 3 | this.name = bookname; 4 | this.price = price; 5 | }; 6 | 7 | /** 在类的原型上添加属性和方法,有两种方式,一种是一一为源性对象属性赋值,另一种则是将一个对象赋值给类的原型对象。但这两种不要混用 */ 8 | Book.prototype.display = function() { 9 | // 展示这本书 10 | }; 11 | 12 | // 或者 13 | Book.prototype = { 14 | display: function() {} 15 | }; 16 | 17 | var book = new Book(10, "JavaScript设计模式", 50); 18 | console.log(book.bookname); 19 | -------------------------------------------------------------------------------- /chapter_11/11.4JSONP.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /chapter_02/2.5多态_1.js: -------------------------------------------------------------------------------- 1 | /** 多态:同一个方法多种调用方式 */ 2 | 3 | function add() { 4 | // 获取参数 5 | var arg = arguments, 6 | len = arg.length; 7 | switch (len) { 8 | // 如果没有参数 9 | case 0: 10 | return 10; 11 | case 1: 12 | return 10 + arg[0]; 13 | case 2: 14 | return arg[0] + arg[1]; 15 | } 16 | } 17 | 18 | // 测试用例 19 | console.log(add()); // 10 20 | console.log(add(5)); // 15 21 | console.log(add(6, 7)); // 13 22 | -------------------------------------------------------------------------------- /chapter_03/3.3一个对象有时候也可代替许多类_1.js: -------------------------------------------------------------------------------- 1 | /** 工厂模式 */ 2 | 3 | function createBook(name, time, type) { 4 | // 创建一个对象,并对对象拓展属性和方法 5 | var o = {}; 6 | o.name = name; 7 | o.type = type; 8 | o.time = time; 9 | o.getName = function() { 10 | console.log(this.name); 11 | }; 12 | // 将对象返回 13 | return o; 14 | } 15 | 16 | var book1 = createBook("js book", 2014, "js"); 17 | var book2 = createBook("css book", 2013, "css"); 18 | 19 | book1.getName(); 20 | book2.getName(); 21 | -------------------------------------------------------------------------------- /chapter_09/9.2兼容方式.js: -------------------------------------------------------------------------------- 1 | /** 外观模式实现 */ 2 | 3 | function addEvent(dom, type, fn) { 4 | // 对于支持DOM2级事件处理程序addEventListener方法的浏览器 5 | if (dom.addEventListener) { 6 | dom.addEventListener(type, fn, false); 7 | } else if (dom.attachEvent) { 8 | // 对于不支持addEventListener方法但支持attchEvent方法的浏览器 9 | dom.attachEvent("on" + type, fn); 10 | } else { 11 | // 对于不支持addEventListener方法,也不支持attchEvent方法,但支持“on”+事件名的浏览器 12 | dom["on" + type] = fn; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter_03/3.3使用工厂模式改进需求_2.js: -------------------------------------------------------------------------------- 1 | function createPop(type, text) { 2 | // 创建一个对象,并对对象拓展属性和方法 3 | var o = {}; 4 | o.content = text; 5 | o.show = function() { 6 | // 显示方法 7 | }; 8 | if (type == "alert") { 9 | // 警示框差异部分 10 | } 11 | if (type == "prompt") { 12 | // 提示框差异部分 13 | } 14 | if (type == "confirm") { 15 | // 确认框差异部分 16 | } 17 | // 将对象返回 18 | return o; 19 | } 20 | // 创建警示框 21 | var userNameAlert = createPop("alert", "用户名只能是26个字母和数字"); 22 | -------------------------------------------------------------------------------- /chapter_04/4.3安全模式类.js: -------------------------------------------------------------------------------- 1 | /** 使用安全模式类可以屏蔽创建类的实例时,忽略使用new关键字造成的错误 */ 2 | 3 | var Demo = function() {}; 4 | Demo.prototype = { 5 | show: function() { 6 | console.log("成功获取!"); 7 | } 8 | }; 9 | 10 | var d = new Demo(); 11 | d.show(); // 成功获取! 12 | var t = Demo(); 13 | t.show(); // Uncaught TypeError: Cannot read property 'show' of undefined 14 | 15 | /** 安全模式类 */ 16 | var Demo = function() { 17 | if (!(this instanceof Demo)) { 18 | return new Demo(); 19 | } 20 | }; 21 | 22 | var d = Demo(); 23 | d.show(); // 成功获取! 24 | -------------------------------------------------------------------------------- /chapter_10/10.6数据适配.js: -------------------------------------------------------------------------------- 1 | /** 应用适配器模式将数组转换为对象形式 */ 2 | 3 | var arr = ["JavaScript", "book", "前端编程语言", "8月1日"]; 4 | 5 | // 目标格式 6 | var obj = { 7 | name: "", 8 | type: "", 9 | title: "", 10 | time: "" 11 | }; 12 | 13 | function arrToObjAdapter(arr) { 14 | return { 15 | name: arr[0], 16 | type: arr[1], 17 | title: arr[2], 18 | time: arr[3] 19 | }; 20 | } 21 | 22 | var adapterData = arrToObjAdapter(arr); 23 | console.log(adapterData); // Object {name: "JavaScript", type: "book", title: "前端编程语言", time: "8月1日"} 24 | -------------------------------------------------------------------------------- /chapter_02/2.3.5寄生式继承.js: -------------------------------------------------------------------------------- 1 | /** 寄生式继承 */ 2 | 3 | function inheritObject(o) { 4 | // 声明一个过渡函数对象 5 | function F() {} 6 | // 过渡对象的原型继承父对象 7 | F.prototype = o; 8 | // 返回过渡对象的一个实例,该实例的原型继承了父对象 9 | return new F(); 10 | } 11 | 12 | // 声明基对象 13 | var book = { 14 | name: "js book", 15 | alikeBook: ["css book", "html book"] 16 | }; 17 | 18 | function createBook(obj) { 19 | // 通过原型继承方式创建新对象 20 | var o = new inheritObject(obj); 21 | // 拓展新对象 22 | o.getName = function(){ 23 | console.log(name); 24 | }; 25 | // 返回拓展后的新对象 26 | return o; 27 | } 28 | -------------------------------------------------------------------------------- /chapter_08/8.6惰性单例.js: -------------------------------------------------------------------------------- 1 | /** 有时候对于单例对象需要延迟创建,所以在单例中还存在一种延迟创建的形式,有人也称之为“惰性单例” */ 2 | 3 | // 惰性单例模式 4 | var LarySingle = (function() { 5 | // 单例实例引用 6 | var _instance = null; 7 | // 单例 8 | function Single() { 9 | // 这里定义私有属性和方法 10 | return { 11 | publicMethod: function() {}, 12 | publicProperty: "1.0" 13 | }; 14 | } 15 | // 获取单例对象接口 16 | return function() { 17 | // 如果未创建单例将创建单例 18 | if(!_instance){ 19 | _instance = Single(); 20 | } 21 | // 返回单例 22 | return _instance; 23 | }; 24 | })(); 25 | -------------------------------------------------------------------------------- /chapter_09/9.3除此之外.js: -------------------------------------------------------------------------------- 1 | // 获取事件对象 2 | var getEvent = function(evnet) { 3 | // 标准浏览器返回event,IE下window.event 4 | return event || window.event; 5 | }; 6 | 7 | // 获取元素 8 | var getTarget = function(event) { 9 | var event = getEvent(event); 10 | // 标准浏览器下 event.target,IE下event.srcElement 11 | return event.target || event.srcElement; 12 | }; 13 | 14 | // 组织默认行为 15 | var preventDefault = function(event) { 16 | var event = getEvent(event); 17 | // 标准浏览器 18 | if (event.preventDefault) { 19 | event.preventDefault(); 20 | } else { 21 | // IE浏览器 22 | event.returnValue = false; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /chapter_01/1.10可以链式添加吗.js: -------------------------------------------------------------------------------- 1 | Function.prototype.addMethod = function(name, fn) { 2 | this[name] = fn; 3 | return this; 4 | }; 5 | 6 | // 添加方法就可以这样做了 7 | var methods = function() {}; 8 | Function.addMethod("checkName", function() { 9 | // 验证姓名 10 | }).addMethod("checkEmail", function() { 11 | // 验证邮箱 12 | }); 13 | 14 | /** 同样也可以进行链式调用 15 | * 既然添加方法的时候可以将this返回实现,那么添加的每个方法将this返回就可以实现链式调用 16 | */ 17 | var metods = function() {}; 18 | methods.addMethod("checkName", function() { 19 | // 验证姓名 20 | return this; 21 | }).addMethod("checkEmail", function() { 22 | // 验证邮箱 23 | return this; 24 | }); 25 | 26 | // 调用 27 | methods.checkName().checkEmail(); 28 | -------------------------------------------------------------------------------- /chapter_02/2.3.1类式继承_2.js: -------------------------------------------------------------------------------- 1 | /** 这种类式继承有两个缺点。其一,由于子类听过其原型prototype对父类实例化,继承了父类。所以说父类中的公有属性要是有引用属性。就会在子类中被所有实例共用,因此一个子类的实例更改子类原型从父类构造函数继承来的共有属性就会直接影响到其他子类 */ 2 | 3 | function SuperClass() { 4 | this.books = ["JavaScript", "html", "css"]; 5 | } 6 | 7 | function SubClass() {} 8 | SubClass.prototype = new SuperClass(); 9 | var instance1 = new SubClass(); 10 | var instance2 = new SubClass(); 11 | console.log(instance2.books); // ["JavaScript", "html", "css"] 12 | instance1.books.push("设计模式"); 13 | console.log(instance2.books); // ["JavaScript", "html", "css", "设计模式"] 14 | 15 | /** 其二,由于子类实现的的继承是靠其原型prototype对父类的实例化实现的,因此在创建父类的时候,是无法向父类传递参数的,因而在实例化父类的时候也无法对父类构造函数内的属性进行初始化 */ 16 | -------------------------------------------------------------------------------- /chapter_01/1.7一个检测类.js: -------------------------------------------------------------------------------- 1 | var CheckObject = function() {}; 2 | CheckObject.prototype.checkName = function() { 3 | // 验证姓名 4 | }; 5 | CheckObject.prototype.checkEmail = function() { 6 | // 验证邮箱 7 | }; 8 | CheckObject.prototype.checkPassword = function() { 9 | // 验证密码 10 | }; 11 | 12 | /** 也可以这样做 */ 13 | var CheckObject = function() {}; 14 | CheckObject.prototype = { 15 | checkName: function() { 16 | // 验证姓名 17 | }, 18 | checkEmail: function() { 19 | // 验证邮箱 20 | }, 21 | checkPassword: function() { 22 | // 验证密码 23 | } 24 | }; 25 | 26 | /** 注意:这两种方式不能混用,否则一旦混用,如在后面为对象的原型对象复制新对象时,那么他将会覆盖掉之前对prototype对象赋值的方法 */ 27 | 28 | // 调用 29 | var a = new CheckObject(); 30 | a.checkName(); 31 | a.checkEmail(); 32 | a.checkPassword(); 33 | -------------------------------------------------------------------------------- /chapter_02/2.3.1类式继承_1.js: -------------------------------------------------------------------------------- 1 | /** 类式继承 */ 2 | // 声明父类 3 | function SuperClass() { 4 | this.superValue = true; 5 | } 6 | // 为父类添加公有方法 7 | SuperClass.prototype.getSuperValue = function() { 8 | return this.superValue; 9 | }; 10 | // 声明子类 11 | function SubClass() { 12 | this.SubValue = false; 13 | } 14 | 15 | // 继承父类 16 | SubClass.prototype = new SuperClass(); 17 | // 为子类添加公有方法 18 | SubClass.prototype.getSubValue = function() { 19 | return this.SubValue; 20 | }; 21 | 22 | var instance = new SubClass(); 23 | console.log(instance.getSuperValue()); // true 24 | console.log(instance.getSubValue()); // false 25 | 26 | console.log(instance instanceof SuperClass); // true 27 | console.log(instance instanceof SubClass); // true 28 | console.log(SubClass instanceof SuperClass); // false 29 | console.log(SubClass.prototype instanceof SuperClass); // true 30 | -------------------------------------------------------------------------------- /chapter_02/2.3.2构造函数继承.js: -------------------------------------------------------------------------------- 1 | /** 构造函数式继承 */ 2 | // 声明父类 3 | function SuperClass(id) { 4 | // 引用类型公有属性 5 | this.books = ["JavaScript", "html", "css"]; 6 | // 值类型公有属性 7 | this.id = id; 8 | } 9 | 10 | // 父类声明原型方法 11 | SuperClass.prototype.showBooks = function() { 12 | console.log(this.books); 13 | }; 14 | 15 | // 声明子类 16 | function SubClass(id) { 17 | // 继承父类 18 | SuperClass.call(this, id); 19 | } 20 | 21 | // 创建第一个子类的示例 22 | var instance1 = new SubClass(10); 23 | var instance2 = new SubClass(11); 24 | 25 | instance1.books.push("设计模式"); 26 | console.log(instance1.books); // ["JavaScript", "html", "css", "设计模式"]; 27 | console.log(instance1.id); // 10 28 | console.log(instance2.books); // ["JavaScript", "html", "css"] 29 | console.log(instance2.id); // 11 30 | 31 | instance1.showBooks(); // TypeError 32 | 33 | /** 由于这类继承没有涉及原型prototype,所以父类的原型的方法自然不会被子类继承。 */ 34 | -------------------------------------------------------------------------------- /chapter_02/2.5多态_2.js: -------------------------------------------------------------------------------- 1 | /** 也可以将多态转化为更易懂的类形式 */ 2 | function Add() { 3 | // 无参数算法 4 | function zero() { 5 | return 10; 6 | } 7 | // 一个参数算法 8 | function one(num) { 9 | return num + 10; 10 | } 11 | // 两个参数算法 12 | function two(num1, num2) { 13 | return num1 + num2; 14 | } 15 | // 相加公有方法 16 | this.add = function() { 17 | var arg = arguments, 18 | len = arg.length; 19 | switch (len) { 20 | // 如果没有参数 21 | case 0: 22 | return zero(); 23 | case 1: 24 | return one(arg[0]); 25 | case 2: 26 | return two(arg[0], arg[1]); 27 | } 28 | }; 29 | } 30 | 31 | // 实例化类 32 | var A = new Add(); 33 | // 测试 34 | console.log(A.add()); // 10 35 | console.log(A.add(5)); // 15 36 | console.log(A.add(6, 7)); // 13 37 | -------------------------------------------------------------------------------- /chapter_01/1.8方法还可以这样用.js: -------------------------------------------------------------------------------- 1 | var CheckObject = { 2 | checkName: function() { 3 | // 验证姓名 4 | return this; 5 | }, 6 | checkEmail: function() { 7 | // 验证邮箱 8 | return this; 9 | }, 10 | checkPassword: function() { 11 | // 验证密码 12 | return this; 13 | } 14 | }; 15 | 16 | // 调用 17 | CheckObject.checkName().checkEmail().checkPassword(); 18 | 19 | /** 同样的方式也可以放到类的原型对象中 */ 20 | var CheckObject = function() {}; 21 | CheckObject.prototype = { 22 | checkName: function() { 23 | // 验证姓名 24 | return this; 25 | }, 26 | checkEmail: function() { 27 | // 验证邮箱 28 | return this; 29 | }, 30 | checkPassword: function() { 31 | // 验证密码 32 | return this; 33 | } 34 | }; 35 | 36 | // 调用的时候需要先创建一下 37 | var a = new CheckObject(); 38 | a.checkName().checkEmail().checkPassword(); 39 | -------------------------------------------------------------------------------- /chapter_01/1.9函数的祖先.js: -------------------------------------------------------------------------------- 1 | /** 2 | * prototype.js是什么 3 | * 一款JavaScript框架,里面为我们方便的封装了很多方法,他最大的特点是对原生对象(JavaScript语言为们提供的对象类,如Function、Array、Object等等)的拓展。 4 | * 例如我们想给每一个函数都添加一个检测邮箱的方法可以这么做 5 | */ 6 | 7 | Function.prototype.checkEmail = function() { 8 | // 验证邮箱 9 | }; 10 | 11 | // 这时候调用就比较方便了 12 | var f = function() {}; 13 | f.checkEmail(); 14 | 15 | // 如果你习惯类的形式,也可以这么用 16 | var f = new Function(); 17 | f.checkEmail(); 18 | 19 | /** 这样做会无缘原生对象Function,所以别人创建的函数也会被你创建的函数所污染,造成不必要的开销,但是你可以抽象出一个统一添加方法的功能方法 */ 20 | Function.prototype.addMethod = function(name, fn) { 21 | this[name] = fn; 22 | }; 23 | 24 | // 如果你想添加永祥验证和姓名验证方法你可以这样做 25 | var methods = function() {}; 26 | // 或者 27 | var methods = new Function(); 28 | methods.addMethod("checkName", function() {}); 29 | methods.addMethod("checkEmail", function() {}); 30 | 31 | // 调用 32 | methods.checkEmail(); 33 | methods.checkName(); 34 | -------------------------------------------------------------------------------- /chapter_02/2.4.1单继承.js: -------------------------------------------------------------------------------- 1 | /** 单继承 属性复制 */ 2 | var extend = function(target, source) { 3 | for (var property in source) { 4 | // 将对象中的属性复制到目标对象中 5 | target[property] = source[property]; 6 | } 7 | // 返回目标对象 8 | return target; 9 | }; 10 | 11 | // 测试用例 12 | var book = { 13 | name: "JavaScript设计模式", 14 | alike: ["css", "html", "JavaScript"] 15 | }; 16 | var anotherBook = { 17 | color: "blue" 18 | }; 19 | extend(anotherBook, book); 20 | console.log(anotherBook.name); // JavaScript设计模式 21 | console.log(anotherBook.alike); // ["css", "html", "JavaScript"] 22 | 23 | anotherBook.alike.push("ajax"); 24 | anotherBook.name = "设计模式"; 25 | console.log(anotherBook.name); // 设计模式 26 | console.log(anotherBook.alike); // ["css", "html", "JavaScript", "ajax"] 27 | console.log(book.name); // JavaScript设计模式 28 | console.log(book.alike); // ["css", "html", "JavaScript", "ajax"] 29 | -------------------------------------------------------------------------------- /chapter_09/9.4小型代码库.js: -------------------------------------------------------------------------------- 1 | // 简约版属性样式库方法 2 | var A = { 3 | // 通过id获取元素 4 | g: function(id) { 5 | return document.getElementById(id); 6 | }, 7 | // 设置css属性 8 | css: function(id, key, value) { 9 | document.getElementById(id).style[key] = value; 10 | }, 11 | // 设置元素的属性 12 | attr: function(id, key, value) { 13 | document.getElementById(id)[key] = value; 14 | }, 15 | html: function(id, html) { 16 | document.getElementById(id).innerHTML = html; 17 | }, 18 | // 为元素绑定事件 19 | on: function(id, type, fn) { 20 | document.getElementById(id)["on" + type] = fn; 21 | } 22 | }; 23 | 24 | // 测试 25 | A.css("box", "background", "red"); // 设置css样式 26 | A.attr("box", "className", "box"); // 设置class 27 | A.html("box", "这是新添加的内容"); // 设置内容 28 | A.on("box", "click", function() { // 绑定事件 29 | A.css("box", "width", "500px"); 30 | }); 31 | -------------------------------------------------------------------------------- /chapter_03/3.1工作中的第一次需求.js: -------------------------------------------------------------------------------- 1 | /** 简单工厂模式,又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象 */ 2 | 3 | // 反面案例 4 | // 用户名输入警示框 5 | var LoginAlert = function(text) { 6 | this.content = text; 7 | }; 8 | LoginAlert.prototype.show = function() { 9 | // 显示警示框 10 | }; 11 | var userNameAlert = new LoginAlert(); 12 | userNameAlert.show(); 13 | 14 | // 在输入密码功能中也调用警示框类 15 | var passwordAlert = new LoginAlert(); 16 | passwordAlert.show(); 17 | 18 | /** 在警示框中添加一个按钮 */ 19 | // 重新创建一个类 20 | var loginConfirm = function(text) { 21 | this.content = text; 22 | }; 23 | loginConfirm.prototype.show = function() { 24 | // 显示确认框 25 | }; 26 | var loginFailConfirm = new loginConfirm("您的用户名不存在,请重新输入"); 27 | loginFailConfirm.show(); 28 | 29 | /** 在警示框中添加输入框 */ 30 | // 重新创建一个类 31 | var LoginPrompt = function(text) { 32 | this.content = text; 33 | }; 34 | LoginPrompt.prototype.show = function() { 35 | // 显示提示框 36 | }; 37 | -------------------------------------------------------------------------------- /chapter_02/2.2.3闭包的实现_1.js: -------------------------------------------------------------------------------- 1 | var Book = (function() { 2 | // 静态私有属性 3 | var bookNum = 0; 4 | // 静态私有方法 5 | function checkBook(name) {} 6 | 7 | // 返回构造函数 8 | return function(newId, newName, newPrice) { 9 | // 私有变量 10 | var name, price; 11 | // 私有方法 12 | function checkId(id) {} 13 | 14 | // 特权方法 15 | this.getName = function() {}; 16 | this.getPrice = function() {}; 17 | this.setName = function() {}; 18 | this.setPrice = function() {}; 19 | // 公有属性 20 | this.id = newId; 21 | // 公有方法 22 | this.copy = function() {}; 23 | bookNum++; 24 | if (bookNum > 100) { 25 | throw new Error("我们仅出版100本书"); 26 | } 27 | // 构造器 28 | this.setName(name); 29 | this.setPrice(price); 30 | }; 31 | })(); 32 | 33 | Book.prototype = { 34 | // 静态公有属性 35 | isJSBook: false, 36 | // 静态公有方法 37 | display: function() {} 38 | }; 39 | -------------------------------------------------------------------------------- /chapter_07/7.5原型继承.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 基于已经存在的模板对象克隆出新对象的模式 3 | * arguments[0],arguments[1],arguments[2]:参数1,参数2,参数3 表示模板对象 4 | * 注意。这里对模板引用类型的属性实际上进行了浅复制(引用类型属性共享),当然根据需求也可以进行深复制(引用类型属性赋值) 5 | **/ 6 | 7 | function prototypeExtend() { 8 | var F = function() {}, // 缓存类,为实例化返回对象临时创建 9 | args = arguments, 10 | i = 0, 11 | len = args.length; 12 | for (; i < len; i++) { 13 | // 遍历每个模板对象中的属性 14 | for (var j in args[i]) { 15 | // 将这些属性复制到缓存类原型中 16 | F.prototype[j] = args[i][j]; 17 | } 18 | } 19 | // 返回缓存类的一个实例 20 | return new F(); 21 | } 22 | 23 | var penguin = prototypeExtend({ 24 | speed: 20, 25 | swim: function() { 26 | console.log("游泳速度 " + this.speed); 27 | } 28 | }, { 29 | run: function(speed) { 30 | console.log("奔跑速度 " + speed); 31 | } 32 | }, { 33 | jump: function() { 34 | console.log("跳跃动作"); 35 | } 36 | }); 37 | 38 | penguin.swim(); 39 | penguin.run(10); 40 | penguin.jump(); 41 | -------------------------------------------------------------------------------- /chapter_02/2.3.4原型式继承.js: -------------------------------------------------------------------------------- 1 | /** 原型式继承 */ 2 | function inheritObject(o) { 3 | // 声明一个过渡函数对象 4 | function F() {} 5 | // 过渡对象的原型继承符对象 6 | F.prototype = o; 7 | // 返回过渡对象的一个实例,该实例的原型继承了父对象 8 | return new F(); 9 | } 10 | 11 | // 测试用例 12 | var book = { 13 | name: "js book", 14 | alikeBook: ["css book", "html book"] 15 | }; 16 | 17 | var newBook = inheritObject(book); 18 | newBook.name = "ajax book"; 19 | newBook.alikeBook.push("xml book"); 20 | 21 | var otherBook = inheritObject(book); 22 | otherBook.name = "flash book"; 23 | otherBook.alikeBook.push("as book"); 24 | 25 | console.log(newBook.name); // ajax book 26 | console.log(newBook.alikeBook); // ["css book", "html book", "xml book", "as book"] 27 | console.log(otherBook.name); // flash book 28 | console.log(otherBook.alikeBook); // ["css book", "html book", "xml book", "as book"] 29 | console.log(book.name); // js book 30 | console.log(book.alikeBook); // ["css book", "html book", "xml book", "as book"] 31 | 32 | /** 跟类式继承一样,引用类型的属性被共用 */ 33 | -------------------------------------------------------------------------------- /chapter_02/2.2.3闭包的实现_2.js: -------------------------------------------------------------------------------- 1 | /** 在闭包外部添加原型属性和方法看上去像似脱离了闭包这个类,所以在有时候在闭包内部实现一个完整的类然后将其返回 */ 2 | var Book = (function() { 3 | // 静态私有变量 4 | var bookNum = 0; 5 | // 静态私有方法 6 | function checkBook(name) {} 7 | // 创建类 8 | function _book(newId, newName, newPrice) { 9 | // 私有变量 10 | var name, price; 11 | // 私有方法 12 | function checkID(id) {} 13 | // 特权方法 14 | this.getName = function() {}; 15 | this.getPrice = function() {}; 16 | this.setName = function() {}; 17 | this.setPrice = function() {}; 18 | // 公有属性 19 | this.id = newId; 20 | // 公有方法 21 | this.copy = function() {}; 22 | bookNum++; 23 | if (bookNum > 100) { 24 | throw new Error("我们仅出版100本书。"); 25 | } 26 | // 构造器 27 | this.setName(name); 28 | this.setPrice(price); 29 | } 30 | // 构造原型 31 | _book.prototype = { 32 | // 静态公有属性 33 | isJSBook: false, 34 | display: function() {} 35 | }; 36 | })(); 37 | -------------------------------------------------------------------------------- /chapter_02/2.2.2属性与方法的封装.js: -------------------------------------------------------------------------------- 1 | // 私有属性与私有方法,对象公有属性和对象公有方法,构造器 2 | var Book = function(id, name, price) { 3 | // 私有属性 4 | var num = 1; 5 | // 私有方法 6 | function checkId() {} 7 | // 特权方法 8 | this.getName = function() {}; 9 | this.getPrice = function() {}; 10 | this.setName = function() {}; 11 | this.setPrice = function() {}; 12 | // 对象公有属性 13 | this.id = id; 14 | this.copy = function() {}; 15 | // 构造器 16 | this.setName(name); 17 | this.setPrice(price); 18 | }; 19 | 20 | // 类静态公有属性(对象不能访问) 21 | Book.isChinese = true; 22 | // 类静态公有方法(对象不能访问) 23 | Book.resetTime = function() { 24 | console.log("new Time"); 25 | }; 26 | Book.prototype = { 27 | // 公有属性 28 | isJSBook: false, 29 | // 公有方法 30 | display: function() {} 31 | }; 32 | 33 | var b = new Book(11, "JavaScript设计模式", 50); 34 | console.log(b.num); // undefined 35 | console.log(b.isJSBook); // false 36 | console.log(b.id); // 11 37 | console.log(b.isChinese); // undefined 38 | 39 | console.log(Book.isChinese); // true 40 | Book.resetTime(); // new Time 41 | -------------------------------------------------------------------------------- /chapter_10/10.4适配异类框架.js: -------------------------------------------------------------------------------- 1 | // 定义框架 2 | var A = A || {}; 3 | // 通过ID获取元素 4 | A.g = function(id) { 5 | return document.getElementById(id); 6 | }; 7 | // 为元素绑定事件 8 | A.on = function(id, type, fn) { 9 | // 如果传递参数是字符串则以id处理,否则以元素对象处理 10 | var dom = typeof id === "string" ? this.g(id) : id; 11 | // 标准DOM2级添加事件方式 12 | if (dom.addEventListener) { 13 | dom.addEventListener(type, fn, false); 14 | } else if (dom.attachEvent) { 15 | dom.attachEvent("on" + type, fn); 16 | } else { 17 | // 简易添加事件方式 18 | dom["on" + type] = fn; 19 | } 20 | }; 21 | 22 | /** 测试 */ 23 | A.on(window, "load", function() { 24 | // 按钮点击事件 25 | A.on("mybutton", "click", function() { 26 | // do something; 27 | }); 28 | }); 29 | 30 | /** 应用适配器模式调用jquery */ 31 | A.g = function(id) { 32 | // 通过jQuery获取jQuery对象,然后返回第一个成员 33 | return $(id).get(0); 34 | }; 35 | 36 | A.on = function(id, type, fn) { 37 | // 如果传递参数是字符串则以id处理,否则以元素对象处理 38 | var dom = typeof id === "string" ? $("#" + id) : $(id); 39 | dom.on(type, fn); 40 | }; 41 | -------------------------------------------------------------------------------- /chapter_07/7.2创建一个焦点图.js: -------------------------------------------------------------------------------- 1 | // 图片轮播类 2 | var LoopImages = function(imgArr, container) { 3 | this.imagesArray = imgArr; // 轮播图片数组 4 | this.container = container; // 轮播图片容器 5 | this.createImage = function() {}; // 创建轮播图片 6 | this.changeImage = function() {}; // 切换下一张图片 7 | }; 8 | 9 | // 上下滑动切换类 10 | var SliderLoopImg = function(imgArr, container) { 11 | // 构造函数继承图片轮播类 12 | LoopImages.call(this, imgArr, container); 13 | // 重写继承的“切换下一张图片”方法 14 | this.changeImage = function() { 15 | console.log("SliderLoopImg changeImage function"); 16 | }; 17 | }; 18 | 19 | // 渐隐切换类 20 | var FadeLoopImg = function(imgArr, container, arrow) { 21 | LoopImages.call(this, imgArr, container); 22 | this.arrow = arrow; 23 | this.changeImage = function() { 24 | console.log("FadeLoopImg changeImage function"); 25 | }; 26 | }; 27 | 28 | /** 测试用例 */ 29 | // 实例化一个渐隐切换图片类 30 | var fadeImg = new FadeLoopImg(["001.jpg", "002.jpg", "003.jpg"], "slide", ["left.jpg", "right.jpg"]); 31 | 32 | fadeImg.changeImage(); // FadeLoopImg changeImage function 33 | -------------------------------------------------------------------------------- /chapter_02/2.4.2多继承.js: -------------------------------------------------------------------------------- 1 | /** 多继承 属性复制 */ 2 | var mix = function() { 3 | var i = 1, // 从第二个参数开始为被继承的对象 4 | leng = arguments.length, // 获取参数长度 5 | target = arguments[0], // 第一个参数为目标对象 6 | arg; // 缓存参数对象 7 | // 遍历被继承的对象 8 | for (; i < len; i++) { 9 | // 缓存当前对象 10 | arg = arguments[i]; 11 | // 遍历被继承对象中的属性 12 | for (var variable in arg) { 13 | // 将被继承对象中的属性复制到目标对象中 14 | target[variable] = arg[variable]; 15 | } 16 | } 17 | 18 | // 返回目标对象 19 | return target; 20 | }; 21 | 22 | /** mix方法的作用就是将传入的多个对象的属性复制到源对象中,这样既可实现多个对象的属性的继承 */ 23 | /** 也可以将他绑定到原生对象Object上,这样所有的对象就可以拥有这个方法了 */ 24 | 25 | Object.prototype.mix = function() { 26 | var i = 0, 27 | len = arguments.length, 28 | arg; 29 | // 遍历被继承的对象 30 | for (; i < len; i++) { 31 | // 缓存当前对象 32 | arg = arguments[i]; 33 | // 遍历被继承对象中的属性 34 | for (var variable in object) { 35 | // 将被继承对象中的属性复制到目标对象中 36 | this[variable] = arg[variable]; 37 | } 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /chapter_02/2.2.4创建对象的安全模式.js: -------------------------------------------------------------------------------- 1 | /** 在JavaScript创建对象时有一种安全模式就可以安全解决忘记使用new关键字而引发的错误 */ 2 | /** 反面示例 */ 3 | var Book = function(title, time, type) { 4 | this.title = title; 5 | this.time = time; 6 | this.type = type; 7 | }; 8 | 9 | // 实例化一本书 10 | var book = Book("JavaScript", "2014", "js"); 11 | console.log(book); // undefined 12 | console.log(window.title); // JavaScript 13 | console.log(window.time); // 2014 14 | console.log(window.type); // js 15 | 16 | /** 图书安全类 */ 17 | var Book = function(title, time, type) { 18 | // 判断执行过程中this是否是当前这个对象(如果是用new创建的) 19 | if (this instanceof Book) { 20 | this.title = title; 21 | this.time = time; 22 | this.type = type; 23 | } else { 24 | // 否则重新创建这个对象 25 | return new Book(title, time, type); 26 | } 27 | }; 28 | 29 | var book = Book("javaScript", "2014", "js"); 30 | 31 | // 测试 32 | console.log(book); // Book 33 | console.log(book.title); // JavaScript 34 | console.log(book.time); // 2014 35 | console.log(book.type); // js 36 | console.log(window.title); // undefined 37 | console.log(window.type); // undefined 38 | console.log(window.time); // undefined 39 | -------------------------------------------------------------------------------- /chapter_02/2.3.3组合继承.js: -------------------------------------------------------------------------------- 1 | /** 类式继承是通过子类的原型prototype对父类实例化来实现的,构造函数式继承是通过在子类的构造函数作用环境中执行一次父类的构造函数来实现的,组合继承只要同时做到两点即可 */ 2 | 3 | /** 组合式继承 */ 4 | // 声明父类 5 | function SuperClass() { 6 | // 值类型公有属性 7 | this.name = name; 8 | // 引用类型公有属性 9 | this.books = ["html", "css", "JavaScript"]; 10 | } 11 | 12 | // 父类原型公有方法 13 | SuperClass.prototype.getName = function() { 14 | console.log(this.name); 15 | }; 16 | 17 | // 声明子类 18 | function SubClass(name, time) { 19 | // 构造函数式继承父类属性 20 | SuperClass.call(this, name); 21 | // 子类中新增公有属性 22 | this.time = time; 23 | } 24 | 25 | // 类式继承 子类原型继承父类 26 | SubClass.prototype = new SuperClass(); 27 | // 子类原型方法 28 | SubClass.prototype.getTime = function() { 29 | console.log(this.time); 30 | }; 31 | 32 | // 测试 33 | var instance1 = new SubClass("js book", 2014); 34 | instance1.books.push("设计模式"); 35 | console.log(instance1.books); // ["html", "css", "JavaScript", "设计模式"] 36 | instance1.getName(); // js book; 37 | instance1.getTime(); // 2014 38 | 39 | var instance2 = new SubClass("css book", 2013); 40 | console.log(instance2.books); // ["html", "css", "JavaScript"] 41 | instance1.getName(); // css book; 42 | instance1.getTime(); // 2013 43 | 44 | /** 这种继承方式在使用构造函数继承时执行了一遍父类的构造函数,而在实现子类原型的类式继承时又调用了一遍父类构造函数,因此父类构造函数调用了两遍,所以这种继承方式并不是最完美的方式 */ 45 | -------------------------------------------------------------------------------- /chapter_03/3.2如果类太多,那么提供一个.js: -------------------------------------------------------------------------------- 1 | /** 简单工厂模式 */ 2 | 3 | // 篮球基类 4 | var Basketball = function() { 5 | this.intro = "篮球盛行于美国。"; 6 | }; 7 | Basketball.prototype = { 8 | getMember: function() { 9 | console.log("每个队伍中需要5名队员。"); 10 | }, 11 | getBallSize: function() { 12 | console.log("篮球很大。"); 13 | } 14 | }; 15 | 16 | // 足球基类 17 | var Football = function() { 18 | this.intro = "足球在世界范围内很流行。"; 19 | }; 20 | Football.prototype = { 21 | getMember: function() { 22 | console.log("每个队伍需要11名队员。"); 23 | }, 24 | getBallSize: function() { 25 | console.log("足球很大"); 26 | } 27 | }; 28 | 29 | // 网球基类 30 | var Tennis = function() { 31 | this.intro = "每年有很多网球系列赛。"; 32 | }; 33 | Tennis.prototype = { 34 | geMember: function() { 35 | console.log("每个队伍需要一名队员"); 36 | }, 37 | getBallSize: function() { 38 | console.log("网球很小。"); 39 | } 40 | }; 41 | 42 | // 运动工厂 43 | var SportsFactory = function(name) { 44 | switch (name) { 45 | case "NBA": 46 | return new Basketball(); 47 | case "wordCup": 48 | return new Football(); 49 | case "FrenchOpen": 50 | return new Tennis(); 51 | } 52 | }; 53 | 54 | // 调用:创建一个足球 55 | var football = SportsFactory("wordCup"); 56 | console.log(football); 57 | console.log(football.intro); 58 | football.getMember(); 59 | -------------------------------------------------------------------------------- /chapter_02/2.3.6寄生组合式继承.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 寄生式继承 继承原型 3 | * 传递参数 subClass 子类 4 | * 传递参数 superClass 父类 5 | **/ 6 | 7 | function inheritObject(o) { 8 | // 声明一个过渡函数对象 9 | function F() {} 10 | // 过渡对象的原型继承父对象 11 | F.prototype = o; 12 | // 返回过渡对象的一个实例,该实例的原型继承了父对象 13 | return new F(); 14 | } 15 | 16 | function inheritPrototype(subClass, superClass) { 17 | // 复制一份父类的原型保存在变量中 18 | var p = inheritObject(superClass.prototype); 19 | p.constructor = subClass; 20 | subClass.prototype = p; 21 | } 22 | 23 | /** 测试用例 */ 24 | // 定义父类 25 | function SuperClass(name) { 26 | this.name = name; 27 | this.colors = ["red", "blue", "green"]; 28 | } 29 | 30 | //定义父类原型方法 31 | SuperClass.prototype.getName = function() { 32 | console.log(this.name); 33 | }; 34 | 35 | // 定义子类 36 | function SubClass(name, time) { 37 | // 构造函数式继承 38 | SuperClass.call(this,name); 39 | // 子类增强属性 40 | this.time = time; 41 | } 42 | 43 | // 寄生式继承父类原型 44 | inheritPrototype(SubClass,SuperClass); 45 | // 子类新增原型方法 46 | SubClass.prototype.getTime = function(){ 47 | console.log(this.time); 48 | }; 49 | // 创建两个测试方法 50 | var instance1 = new SubClass("js book", 2014); 51 | var instance2 = new SubClass("css book", 2013); 52 | 53 | instance1.colors.push("black"); 54 | console.log(instance1.colors); // ["red", "blue", "green", "black"] 55 | console.log(instance2.colors); // ["red", "blue", "green"] 56 | instance2.getName(); // css book 57 | instance2.getTime(); // 2013 58 | -------------------------------------------------------------------------------- /chapter_04/4.1广告展现.js: -------------------------------------------------------------------------------- 1 | /** 工厂方法模式:通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例 */ 2 | 3 | /** 反面示例 */ 4 | // 创建Java学科类 5 | var Java = function(content) { 6 | // 将内容保存在content里面以备以后使用 7 | this.content = content; 8 | // 创建对象时,通过闭包,直接执行,将内容按需求的样式插入到页面内 9 | (function(content) { 10 | var div = document.createElement("div"); 11 | div.innerHTML = content; 12 | div.style.color = "green"; 13 | document.getElementById('container').appendChild(div); 14 | })(content); 15 | }; 16 | 17 | // 创建PHP学科类 18 | var Php = function(content) { 19 | this.content = content; 20 | (function(content) { 21 | var div = document.createElement("div"); 22 | div.innerHTML = content; 23 | div.style.color = "yellow"; 24 | document.getElementById('container').appendChild(div); 25 | })(content); 26 | }; 27 | 28 | // 创建JavaScript学科类 29 | var JavaScript = function(content) { 30 | this.content = content; 31 | (function(content) { 32 | var div = document.createElement("div"); 33 | div.innerHTML = content; 34 | div.style.color = "pink"; 35 | document.getElementById('container').appendChild(div); 36 | })(content); 37 | }; 38 | 39 | // 学科类工厂 40 | function JobFactory(type, content) { 41 | switch (type) { 42 | case "java": 43 | return new Java(content); 44 | case "php": 45 | return new Php(content); 46 | case "JavaScript": 47 | return new JavaScript(content); 48 | } 49 | } 50 | 51 | // 测试 52 | JobFactory("JavaScript", "JavaScript哪家强"); 53 | 54 | /** 如果此时需求追加在添加一个UI学科,再使用简单工厂模式,便不利于扩展 */ 55 | -------------------------------------------------------------------------------- /chapter_07/7.3最优的解决方案.js: -------------------------------------------------------------------------------- 1 | // 图片轮播类 2 | var LoopImages = function(imgArr, container) { 3 | this.imagesArray = imgArr; 4 | this.container = container; 5 | }; 6 | 7 | LoopImages.prototype = { 8 | // 创建轮播图片 9 | createImage: function() { 10 | console.log("LoopImages createImage function"); 11 | }, 12 | // 切换下一张图片 13 | changeImage: function() { 14 | console.log("LoopImages changeImage function"); 15 | } 16 | }; 17 | 18 | // 上下滑动切换类 19 | var SliderLoopImg = function(imgArr, container) { 20 | // 构造函数继承图片轮播类 21 | LoopImages.call(this, imgArr, container); 22 | }; 23 | SliderLoopImg.prototype = new LoopImages(); 24 | // 重写继承的“切换下一张图片”方法 25 | SliderLoopImg.prototype.changeImage = function() { 26 | console.log("SliderLoopImg changeImage function"); 27 | }; 28 | 29 | // 渐隐切换类 30 | var FadeLoopImg = function(imgArr, container, arrow) { 31 | LoopImages.call(this, imgArr, container); 32 | // 切换箭头私有变量 33 | this.arrow = arrow; 34 | }; 35 | FadeLoopImg.prototype = new LoopImages(); 36 | FadeLoopImg.prototype.changeImage = function() { 37 | console.log("FadeLoopImg changeImage function"); 38 | }; 39 | LoopImages.prototype.getImageLength = function() { 40 | return this.imagesArray.length; 41 | }; 42 | FadeLoopImg.prototype.getContainer = function(){ 43 | return this.container; 44 | }; 45 | /** 测试用例 */ 46 | var fadeImg = new FadeLoopImg(["001.jpg", "002.jpg", "003.jpg"], "slide", ["left.jpg", "right.jpg"]); 47 | console.log(fadeImg.container); // slide 48 | fadeImg.changeImage(); // FadeLoopImg changeImage function 49 | console.log(fadeImg.getImageLength()); // 3 50 | console.log(fadeImg.getContainer()); // slide 51 | -------------------------------------------------------------------------------- /chapter_04/4.4安全的工厂方法.js: -------------------------------------------------------------------------------- 1 | // 安全模式创建的工厂类 2 | var Factory = function(type, content) { 3 | if (this instanceof Factory) { 4 | var s = new this[type](content); 5 | return s; 6 | } else { 7 | return new Factory(type, content); 8 | } 9 | }; 10 | 11 | // 工厂原型中设置创建所有类型数据对象的基类 12 | Factory.prototype = { 13 | Java: function(content) { 14 | // 将内容保存在content里面以备以后使用 15 | this.content = content; 16 | // 创建对象时,通过闭包,直接执行,将内容按需求的样式插入到页面内 17 | (function(content) { 18 | var div = document.createElement("div"); 19 | div.innerHTML = content; 20 | div.style.color = "green"; 21 | document.getElementById('container').appendChild(div); 22 | })(content); 23 | }, 24 | Php: function(content) { 25 | this.content = content; 26 | (function(content) { 27 | var div = document.createElement("div"); 28 | div.innerHTML = content; 29 | div.style.color = "yellow"; 30 | document.getElementById('container').appendChild(div); 31 | })(content); 32 | }, 33 | JavaScript: function(content) { 34 | this.content = content; 35 | (function(content) { 36 | var div = document.createElement("div"); 37 | div.innerHTML = content; 38 | div.style.color = "pink"; 39 | document.getElementById('container').appendChild(div); 40 | })(content); 41 | } 42 | }; 43 | 44 | var data = [{ 45 | type: "JavaScript", 46 | content: "JavaScript哪家强" 47 | }, { 48 | type: "Java", 49 | content: "Java哪家强" 50 | }, { 51 | type: "Php", 52 | content: "php哪家强" 53 | }, { 54 | type: "Php", 55 | content: "UI哪家强" 56 | }, { 57 | type: "Java", 58 | content: "UI哪家强" 59 | }, { 60 | type: "JavaScript", 61 | content: "JavaScript哪家强" 62 | }, { 63 | type: "JavaScript", 64 | content: "JavaScript哪家强" 65 | }]; 66 | 67 | for (var i = 0; i < data.length; i++) { 68 | Factory(data[i].type, data[i].content); 69 | } 70 | -------------------------------------------------------------------------------- /chapter_06/6.2创建对象的另一种形式.js: -------------------------------------------------------------------------------- 1 | // 创建一位人类 2 | var Human = function(params) { 3 | // 技能 4 | this.skill = params && params.skill || "保密"; 5 | // 兴趣爱好 6 | this.hobby = params && params.hobby || "保密"; 7 | }; 8 | 9 | // 人类原型方法 10 | Human.prototype = { 11 | getSkill: function() { 12 | return this.skill; 13 | }, 14 | getHobby: function() { 15 | return this.hobby; 16 | } 17 | }; 18 | 19 | // 实例化姓名类 20 | var Named = function(name) { 21 | var that = this; 22 | // 构造器 23 | // 构造函数解析姓名的姓与名 24 | (function(name, that) { 25 | that.wholeName = name; 26 | if (name.indexOf(" ") > -1) { 27 | that.firstName = name.slice(0, name.indexOf(" ")); 28 | this.secondName = name.slice(name.indexOf(" ")); 29 | } 30 | })(name, that); 31 | }; 32 | 33 | // 实例化职位类 34 | var Work = function(work) { 35 | var that = this; 36 | // 构造器 37 | // 构造函数中通过传入的职位特征来设置相应的职位以及描述 38 | (function(work, that) { 39 | switch (work) { 40 | case "code": 41 | that.work = "工程师"; 42 | that.workDescript = "每天沉醉于编程"; 43 | break; 44 | case "UI": 45 | case "UE": 46 | that.work = "设计师"; 47 | that.workDescript = "设计更似一种艺术"; 48 | break; 49 | case "teach": 50 | that.work = "教师"; 51 | that.workDescript = "分享也是一种快乐"; 52 | break; 53 | default: 54 | that.work = work; 55 | that.workDescript = "对不起,我们现在还不清楚你所选择的职位的相关描述。"; 56 | } 57 | })(work, that); 58 | }; 59 | 60 | // 更换期望的职位 61 | Work.prototype.changeWork = function(work) { 62 | this.work = work; 63 | }; 64 | // 添加对职位的描述 65 | Work.prototype.changeDescript = function(setence) { 66 | this.workDescript = setence; 67 | }; 68 | 69 | /** 70 | * 应聘者建造者 71 | * 参数 name: 姓名(全名) 72 | * 参数 work: 期望职位 73 | **/ 74 | 75 | var Person = function(name, work) { 76 | // 创建应聘者缓存对象 77 | var _person = new Human(); 78 | // 创建应聘者姓名解析对象 79 | _person.name = new Named(name); 80 | // 将创建的应聘者期望职位 81 | _person.work = new Work(work); 82 | // 将创建的应聘者对象返回 83 | return _person; 84 | }; 85 | 86 | /** 测试用例 */ 87 | var person = new Person("xiao ming", "code"); 88 | console.log(person.skill); // 保密 89 | console.log(person.name.firstName); // xiao 90 | console.log(person.work.work); // 工程师 91 | console.log(person.work.workDescript); // 每一天在编程中度过 92 | person.work.changeDescript("更改一下职位描述!"); 93 | console.log(person.work.workDescript); // 更改一下职位描述! 94 | -------------------------------------------------------------------------------- /chapter_05/5.2抽象工厂模式.js: -------------------------------------------------------------------------------- 1 | /** 抽象工厂方法 */ 2 | 3 | var VehicleFactory = function(subType, superType) { 4 | // 判断抽象工厂中是否有该抽象类 5 | if (typeof VehicleFactory[superType] === "function") { 6 | // 缓存类 7 | var F = function() {}; 8 | // 继承父类属性和方法 9 | F.prototype = new VehicleFactory[superType](); 10 | // 将子类 constructor 指向子类 11 | subType.constructor = subType; 12 | // 子类原型继承“父类” 13 | subType.prototype = new F(); 14 | } else { 15 | // 不存在该抽象类抛出错误 16 | throw new Error("未创建该抽象类"); 17 | } 18 | }; 19 | 20 | // 小汽车抽象类 21 | VehicleFactory.Car = function() { 22 | this.type = "car"; 23 | }; 24 | VehicleFactory.Car.prototype = { 25 | getPrice: function() { 26 | return new Error("抽象方法不能调用"); 27 | }, 28 | getSpeed: function() { 29 | return new Error("抽象方法不能调用"); 30 | } 31 | }; 32 | 33 | // 公交车抽象类 34 | VehicleFactory.Bus = function() { 35 | this.type = "bus"; 36 | }; 37 | VehicleFactory.Bus.prototype = { 38 | getPrice: function() { 39 | return new Error("抽象方法不能调用"); 40 | }, 41 | getPassengerNum: function() { 42 | return new Error("抽象方法不能调用"); 43 | } 44 | }; 45 | 46 | // 货车抽象类 47 | VehicleFactory.Truck = function() { 48 | this.type = "truck"; 49 | }; 50 | VehicleFactory.Truck.prototype = { 51 | getPrice: function() { 52 | return new Error("抽象方法不能调用"); 53 | }, 54 | getTrainload: function() { 55 | return new Error("抽象方法不能调用"); 56 | } 57 | }; 58 | 59 | /** 抽象与实现 */ 60 | 61 | // 宝马汽车子类 62 | var BMG = function(price, speed) { 63 | this.price = price; 64 | this.speed = speed; 65 | }; 66 | 67 | // 抽象工厂实现对Car抽象类的继承 68 | VehicleFactory(BMG, "Car"); 69 | BMG.prototype.getPrice = function() { 70 | return this.price; 71 | }; 72 | BMG.prototype.getSpeed = function() { 73 | return this.speed; 74 | }; 75 | 76 | // 兰博基尼汽车子类 77 | var Lamborghini = function(price, speed) { 78 | this.price = price; 79 | this.speed = speed; 80 | }; 81 | // 抽象工厂实现对Car抽象类的继承 82 | VehicleFactory(Lamborghini, "Car"); 83 | Lamborghini.prototype.getPrice = function() { 84 | return this.price; 85 | }; 86 | Lamborghini.prototype.getSpeed = function() { 87 | return this.speed; 88 | }; 89 | 90 | // 宇通汽车类 91 | var YUTONG = function(price, passenger) { 92 | this.price = price; 93 | this.passenger = passenger; 94 | }; 95 | VehicleFactory(YUTONG, "Bus"); 96 | YUTONG.prototype.getPrice = function() { 97 | return this.price; 98 | }; 99 | YUTONG.prototype.getPassengerNum = function() { 100 | return this.getPassengerNum(); 101 | }; 102 | 103 | // 奔驰汽车子类 104 | var BenzTruck = function(price, trainLoad) { 105 | this.price = price; 106 | this.trainLoad = trainLoad; 107 | }; 108 | // 抽象工厂实现对Truck抽象类的继承 109 | VehicleFactory(BenzTruck, "Truck"); 110 | BenzTruck.prototype.getPrice = function() { 111 | return this.price; 112 | }; 113 | BenzTruck.prototype.getTrainload = function() { 114 | return this.trainLoad; 115 | }; 116 | 117 | /** 测试 */ 118 | 119 | var truck = new BenzTruck(1000000,1000); 120 | console.log(truck.getPrice()); // 1000000 121 | console.log(truck.getTrainload()); // 1000 122 | --------------------------------------------------------------------------------