JavaScript设计模式基础-----封装、继承、多态
2017-09-26 15:58
477 查看
// 函数的基本形式 function checkName() { "use strict"; } function checkEmail() { "use strict"; } function checkPassword() { "use strict"; } // 函数的另一种形式 var checkName = function () { "use strict"; } var checkEmail = function () { "use strict"; } var checkPassword = function () { "use strict"; } // 上面两种等于声明了全局变量 // 这个从功能上讲是没有问题的,但是如果别人也定义了同样的方法就会覆盖掉这个函数 /* * 用对象收编变量 * */ var CheckObject = { checkName: function () { "use strict"; }, checkEmail: function () { "use strict"; }, checkPassword: function () { "use strict"; } } // 将所有的函数作为checkObject的方法,这样就只有一个对象 用法:CheckObject.checkName() /* * 对象的另一种形式 * */ var CheckObject = function () { } CheckObject.checkName = function () { "use strict"; } CheckObject.checkEmail = function () { "use strict"; } CheckObject.checkPassword = function () { "use strict"; } //用法:CheckObject.checkName() 不好处就是比人不能复制你的代码,这个对象在用new关键字创建新对象的时候新创建的对象是不能继承这些方法的 /* * 实现简单复制 * */ var CheckObject = function () { "use strict"; return { checkName: function () { "use strict"; }, checkEmail: function () { "use strict"; }, checkPassword: function () { "use strict"; } } } // 这样每个人用的时候都是返回一个新对象 通过new 实例化的时候 互不影响 // 用法:var a= CheckObject(); a.checkName(); /* * 用类的写法 每次new的时候新创建的对象都会有一套自己的方法,这样很消耗内存 * */ var CheckObject = function () { "use strict"; this.checkName = function () { } this.checkEmail = function () { } this.checkPassword = function () { } } // 用法:var a = new CheckObject(); a.checkPassword(); /* 这个对象创建出来的方法就都是相同的,因为他们都需要一来prototype原型一次查找 * */ var CheckObject = function () { "use strict"; } CheckObject.prototype.checkName = function () { "use strict"; } CheckObject.prototype.checkEmail = function () { } CheckObject.prototype.checkPassword = function () { } //简写 var CheckObject = function () { } CheckObject.prototype = { checkName: function () { "use strict"; }, checkEmail: function () { "use strict"; }, checkPassword: function () { "use strict"; } } // 用法:var a = new CheckObject(); a.checkName(); // =================== 注意========================== // 这两种方法不能一起用 一起用的话 后面的prototype 方法会覆盖前面的 var CheckObject = { checkName: function () { "use strict"; return this; }, checkEmail: function () { "use strict"; return this; }, checkPassword: function () { "use strict"; return this; } } // 链式调用 // CheckObject.checkName().checkEmail(); // 也可以放到原型中 var CheckObject = function () { "use strict"; } CheckObject.prototype = { checkName: function () { "use strict"; return this; }, checkEmail: function () { "use strict"; return this; }, checkPassword: function () { "use strict"; return this; } } // 用法:var a = new CheckObject(); a.checkName().checkEmail(); /* 为函数的原型添加方法 * */ Function.prototype.addMethod = function (name, fn) { this[name] = fn; // 如果要添加到prototype上 使用的时候要使用new 关键字 this.prototype[name]=fn; 使用的时候要使用new return this; } var methods = new function (); methods.addMethod('checkName', function () { // 如果要链式调用 返回this }).addMethod('checkEmail', function () { }); methods.chekcName(); // ============================ 面向对象 ============================ // // 创建一个类 var Book = function (id, bookname, price) { this.id = id; this.bookname = bookname; this.price = price; } // 为类添加方法 Book.prototype = { display: function () { } } // 封装 var Book = function (id, name, price) { // 私有属性 相当于php private 定义的方法 var num = 1; // 私有方法 function checkId() { } // 特权方法 相当于php为变量设置和获取值的方法 this.getName = function () { } this.setName = function () { } this.getPrice = function () { } this.setPrice = function () { } // 公有属性 相当于php的public定义的属性和方法 【这相当于css的style 优先级要比prototype的高】 this.id = id; // 公有方法 this.copy = function () { } // 构造器 相当于php的__construct this.setName(name); this.setPrice(price); } // 类外部通过 . 语法定义的属性和方法 称为 静态公有属性和方法 但是对象不能访问 相当于php static 定义的属性和方法 只能通过类名.属性、方法访问 Book.isChinese = true; Book.resetTime = function () { console.log('new time') } // 通过prototype定义的属性和方法称为公有属性和方法 Book.prototype = { // 公有属性 isJsBook: false, // 公有方法 display: function () { } } // 用法 : var b= new Book(11,'JavaScript设计模式',50); /* * 升级版本的封装 function 对象的 * */ function Person(info) { this._init_(info) } Person.prototype = { constructor: Person, _init_: function (info) { this.name = info.name; this.age = info.age; this.sex = info.sex; }, sayHello: function () { console.log('hello'); } } /* * 升级版本2 仿照jquery * */ var Person = (function (window) { var Person = function (name) { // 直接实例化 return new Person.fn.init(name); } Person.fn = Person.prototype = { constructor: Person, init: function (name) { this.name = name; this.sayHello = function () { this.makeArray(); } }, makeArray: function () { console.log(this.name); } } Person.fn.init.prototype = Person.fn; return Person; })(); /* var p = Person('pawn'); console.log(p); p.sayHello(); */ 每个类都有三部分组成 1. 构造函数内部的这是供实例化对象复制用的 2. 构造函数外部的直接通关.语法添加的 只是类使用的 只有类.才可以访问 3. 添加在prototype中的 实例化对象时可以通过原型直接访问到 是给所有实例化对象所共用的 /* * 继承 http://www.cnblogs.com/humin/p/4556820.html * */ // 定义一个动物类 function Animal(name) { // 属性 this.name = name || 'Animal'; // 实例方法 this.sleep = function () { console.log(this.name + '正在睡觉!'); } } // 原型方法 Animal.prototype.eat = function (food) { console.log(this.name + '正在吃:' + food); }; //1、原型链继承 //核心: 将父类的实例作为子类的原型 function Cat() { } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.eat('fish')); console.log(cat.sleep()); //instanceof主要的目的是检测引用类型 //typeof 是一个操作符,主要的目的是检测一个变量是不是基本数据类型的变量 console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true /*特点: 非常纯粹的继承关系,实例是子类的实例,也是父类的实例 父类新增原型方法/原型属性,子类都能访问到 简单,易于实现 缺点: 要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中 无法实现多继承 来自原型对象的引用属性是所有实例共享的(详细请看附录代码: 示例1) 创建子类实例时,无法向父类构造函数传参 推荐指数:★★(3、4两大致命缺陷)*/ //2、构造继承 //核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型) function Cat(name) { "use strict"; Animal.call(this); this.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true /*特点: 解决了1中,子类实例共享父类引用属性的问题 创建子类实例时,可以向父类传递参数 可以实现多继承(call多个父类对象) 缺点: 实例并不是父类的实例,只是子类的实例 只能继承父类的实例属性和方法,不能继承原型属性/方法 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能 推荐指数:★★(缺点3)*/ //3、实例继承 //核心:为父类实例添加新特性,作为子类实例返回 function Cat(name) { "use strict"; var instance = new Animal(); instance.name = name || 'Tom'; return instance; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // false /* 特点: 不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果 缺点: 实例是父类的实例,不是子类的实例 不支持多继承 推荐指数:★★*/ //4、拷贝继承 function Cat(name) { var animal = new Animal(); for (var p in animal) { Cat.prototype[p] = animal[p]; } Cat.prototype.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true /*特点: 支持多继承 缺点: 效率较低,内存占用高(因为要拷贝父类的属性) 无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到) 推荐指数:★(缺点1)*/ /* 5、组合继承 核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用 */ function Cat(name) { Animal.call(this); this.name = name || 'Tom'; } Cat.prototype = new Animal(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // true /*特点: 弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法 既是子类的实例,也是父类的实例 不存在引用属性共享问题 可传参 函数可复用 缺点: 调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了) 推荐指数:★★★★(仅仅多消耗了一点内存)*/ /* 6、寄生组合继承 核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点 */ function Cat(name) { Animal.call(this); this.name = name || 'Tom'; } (function () { // 创建一个没有实例方法的类 在js 中 继承是依赖于原型prototype链实现的 var Super = function () { }; Super.prototype = Animal.prototype; //将实例作为子类的原型 Cat.prototype = new Super(); })(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true /* 特点: 堪称完美 缺点: 实现较为复杂 推荐指数:★★★★(实现复杂,扣掉一颗星) */ //=============================================javascript 多继承======================================================== // 在JavaScript中继承是一来与prototype链实现的。因为只有一条原型链。理论上是不能继承多个父类,但是js是很灵活的。通过一些 //技巧和方法可以实现多继承 /** * 作用就是将传入的多个对象的属性复制到源对象中 这样就可以实现对多个对象属性的继承 * 使用的时候第一个参数----需要传入要继承的对象 * @returns {*} */ var mix = function () { var i = 1,// 从第一个参数起为被继承的对象 len = arguments.length,// 获取参数长度 target = arguments[0],// 第一个对象为目标对象 arg;// 缓存参数对象 for (; i < len; i++) { // 缓存当前对象 arg = arguments[i]; // 遍历被继承对象中的属性 for (var property in arg) { // 将被继承对象中的属性复制的目标对象中 target[property] = arg[property]; } } return target; }; Object.prototype.mix = function () { var i = 0, // 从第一个参数起为被继承的对象 len = arguments.length, // 获取参数长度 arg;// 缓存参数对象 // 遍历被继承的对象 for (; i < len; i++) { // 缓存当前对象 arg = arguments[i]; // 遍历被继承对象中的属性 for (var property in arg) { // 将被继承对象中的属性复制的目标对象中 this[property] = arg[property]; } } }; var book1 = { name: 'book1', alike: ['css', 'js', 'java'] }; var book3 = { names: 'book1', alikes: ['css', 'js', 'java'] }; var book2 = { ccc: 'ccccccc' }; var outhorBook = { color: 'red' }; outhorBook.mix(book1, book2, book3); console.log(outhorBook); /* * ============================================= 多态 ============================================= * 指的是同一种方法多种调用方式 * */ function add() { // 获取参数 var arg = arguments, // 获取长度 len = arg.length; switch (len) { // 如果没有传参数 case 0: return 10; case 1: return 10 + arg[0]; case 2: return arg[0] + arg[1]; } } console.log(add()); // 10 console.log(add(5)); // 15 console.log(add(6, 7)); // 13 // or function Add() { function zero() { return 10; } function one(num) { return 10 + num; } function two(num1, num2) { return num1 + num2; } // 相加共有方法 this.add = function () { var arg = arguments, len = arg.length; switch (len) { case 0: return zero(); case 1: return one(arg[0]); case 2: return two(arg[0], arg[1]) } } } var a = new Add(); console.log(a.add()); console.log(a.add(5)); console.log(a.add(6, 7));
相关文章推荐
- 黑马程序员<java基础<面向对象(封装,继承,多态,抽象)>>
- OC基础——面向对象(封装、继承、多态)
- Java基础 对封装、继承、多态、抽象的理解
- java基础<面向对象>总结(函数、封装、继承、多态)
- Java基础--封装、继承、多态
- java基础回顾---封装继承多态
- Java基础之封装、继承、多态、接口详解
- 1.面向对象基础(封装、继承、多态、抽象类)0711
- OC基础-零基础学习Objective-C:第二部分.封装、继承和多态
- Py修行路 python基础 (十六)面向对象编程的 继承 多态与多态性 封装
- OC基础第三章: 继承 、 封装、多态
- 面向对象基础之二封装继承多态
- 黑马程序员----Java基础之面向对象(封装 继承 多态)
- JAVA初等基础__(面向对象三个特征, 封装,继承,多态)
- java 封装,继承,多态基础
- Java基础总结 - 封装 继承 多态
- Java基础<六>---> 面向对象与java特性(封装、继承、多态
- java基础三大特性——封装、继承与多态
- Python基础(6)- 类和对象(使用、继承、派生、组合、接口、多态、封装、property、staticmethod、classmethod、反射、slots、上下文管理协议、元类)
- 黑马程序员——Java基础---深入理解面向对象(封装继承和多态)