封装类
var Book = function (id, bookname, price) {this.id = id; this.bookname = bookname; this.price = price;};
类的原型
Book.prototype = {display: function () {console.log("展现这本书");
}};
constructor 属性返回对创立此对象的数组函数的援用
var book = new Book(10, 'javascript 设计模式', 50);console.dir(Book);
console.dir(Book.prototype.constructor);//Book Object
console.log(book);
面向对象思维 公有属性 公有办法 共有属性 爱护办法 …
// 公有属性与公有办法,特权办法,对象共有属性和对象共有办法,结构器
var BookTwo = function (id, name, price) {// 公有属性 var num = 1; // 公有办法 function checkId() {console.log(this.id);
}
// 特权办法 this.getName = function () { return this.name;}; this.getPrice = function () { return this.price;}; this.setName = function (name) {this.name = name;}; this.setPrice = function (price) {this.price = price;}; // 对象私有属性 this.id = id; // 对象私有办法 this.copy = function () { console.log('copy');
}; // 结构器 this.setName(name); this.setPrice(price);};
// 类动态私有属性(对象不能拜访)BookTwo.isChinese = true;// 类动态私有办法(对象不能拜访)BookTwo.resetTime = function () { console.log('new Tiem');
};
BookTwo.prototype = { // 私有属性 isJSBook: false,
// 私有办法 display: function () {console.log("显示");
}};
var booktwo = new BookTwo(11, 'javascript 设计模式', 50);
console.log(booktwo);
console.log(booktwo.num);//undefined
console.log(booktwo.isJSBook);//false
booktwo.display();// 显示
console.log(booktwo.id);//11
console.log(booktwo.isChinese);//undefined
// 类的动态私有属性能够通过类的本身拜访
console.log(BookTwo.isChinese);//true
BookTwo.resetTime();//new Time
类的动态变量 通过闭包来实现
// 利用闭包来实现
var BookThree = (function () {// 动态公有变量 var bookNum = 0; // 动态公有办法 function checkBook(name) {console.log(name);
}
// 构造函数 function _book(newId, newName, newPrice) {// 公有变量 var name, price; // 公有办法 function checkID(id) { }
// 特权办法 this.getName = function () { return this.name;}; this.getPrice = function () { return this.price;}; this.setName = function (name) {this.name = name;}; this.setPrice = function (price) {this.price = price;}; // 私有属性 this.id = newId; // 私有办法 this.copy = function () {}; bookNum++; if (bookNum > 100) {throw new Error('咱们仅出版 100 本书');
} // 结构器 this.setName(newName); this.setPrice(newPrice); }
return _book;
})();
var bookThree = new BookThree(11, 'javascript 设计模式', 50);
console.log(bookThree);
创建对象的平安模式 - 去除 new 也可胜利事例化对象
var BookFour = function (id, name, price) {this.id = id; this.name = name; this.price = price;};
var bookFour = BookTwo(12, 'javascript 设计模式', 50);console.log(bookFour);//undefined
console.log(window.id);//12
console.log(window.name);//javascript 设计模式
console.log(window.price);//50
bookFour = new BookTwo(13, 'javascript 设计模式', 50);console.log(bookFour);
// 图书安全类
/*
* instanceof 运算符用来判断一个构造函数的 prototype 属性所指向的对象是否存在另外一个要检测对象的原型链上 * */var BookFive = function (id, name, price) {// 判断执行过程中的 this 是否是以后对象(如果是阐明是 new 创立的)if (this instanceof BookFive) {this.id = id; this.name = name; this.price = price;} else {// 从新创立这个对象 return new BookFive(id, name, price);
}};
// 都能胜利创立
var bookFive = BookFive(14, 'javascript 设计模式', 50);
console.log(bookFive);
bookFive = new BookFive(15, 'javascript 设计模式', 50);
console.log(bookFive);
继承
类式继承 – 要害:SubClass.prototype = new SuperClass();
// 申明父类
function SuperClass() {this.superValue = true;}
// 为父类增加共有办法
SuperClass.prototype.getSuperValue = function () { return this.superValue;};
// 申明子类
function SubClass() {this.subValue = false;}
// 继承父类
SubClass.prototype = new SuperClass();
// 为子类增加共有办法
SubClass.prototype.getSubValue = function () { return this.subValue;};
var instance = new SubClass();
console.log(instance.getSuperValue());
console.log(instance.getSubValue());
/*
* instance 判断对象和类之间的继承关系 实例 -》类 * * 是判断 实例 与 类 的继承关系 * */console.log(instance instanceof SuperClass);//true
console.log(instance instanceof SubClass);//true
console.log(SubClass instanceof SuperClass);//false
console.log(SubClass.prototype instanceof SuperClass);//true
console.log(instance instanceof Object);//true
类式的毛病
- 1. 因为子类通过其原型 prototype 对父类实例化,继承了父类。所以父类中
- 私有的属性要是援用类型,就会在子类中被所有实例共用,因而一个子类的
- 实例更改字类原型从父类构造函数中继承来的共有属性就会间接影响到其余子类
- 2. 因为子类的实现的继承是靠其原型 prototype 对父类的实例化实现的,因
- 此在创立父类的时候,是无奈向父类传递参数的,因此在实例化父类的时候
- 也无奈对父类构造函数类的属性进行初始化
function SuperClassTwo() {this.books = ['Javascript', 'html', 'css'];}
function SubClassTwo() {}
SubClassTwo.prototype = new SuperClassTwo();
var instance1 = new SubClassTwo();
var instance2 = new SubClassTwo();
console.log("类式的毛病");
console.log(instance1.books);//["Javascript", "html", "css"]
instance1.books.push('设计模式');
console.log(instance2.books);//["Javascript", "html", "css", "设计模式"]
总结:在批改 instance1 的时候 instance2 也被批改了这样会造成程序的谬误
- 为了解决这些产生了
- 创立即继承 - 构造函数继承
-
- 要害:SuperClassThree.call(this,id)
// 构造函数式继承
// 申明父类
function SuperClassThree(id) {// 援用类型共有属性 this.books = ['Javascript', 'html', 'css']; // 值类型共有属性 this.id = id;}
// 父类申明原型办法
SuperClassThree.prototype.showBooks = function () { console.log(this.books);
};
// 申明子类
function SubClassThree(id) {// 继承父类 SuperClassThree.call(this, id);
}
// 创立第一个子类的实例
var instance3 = new SubClassThree(10);
// 创立第一个子类的实例
var instance4 = new SubClassThree(11);
instance3.books.push("设计模式");
console.log(instance3.books);//["Javascript", "html", "css", "设计模式"]
console.log(instance3.id);//10
console.log(instance4.books);//["Javascript", "html", "css"]
console.log(instance4.id);//11
- 总结:改过了类式继承的毛病,但还是有毛病,就是每个实例都会独自实例化一份
- 父类的共用办法,这就违反了代码复用的准则,为了综合这两种继承的长处,起初
- 有了 —- 组合式继承
将长处为我所用 – 组合继承
// 组合继承
// 申明父类
function SuperClassFour(name) {// 值类型共有属性 this.name = name; // 援用类型共有属性 this.books = ['html', 'css', 'Javascript']}
// 父类原型共有办法
SuperClassFour.prototype.getName = function () { console.log(this.name);
};
// 申明子类
function SubClassFour(name, time) {// 构造函数式继承父类 name 属性 SuperClassFour.call(this, name);
// 子类中新增共有属性 this.time = time;}
// 类式继承 子类原型继承父类实例
SubClassFour.prototype = new SuperClassFour();
// 子类原型办法
SubClassFour.prototype.getTime = function () { console.log(this.time);
};
console.log('将长处为我所用 -- 组合继承');
var instance5 = new SubClassFour('js book', 2014);
console.log(instance5);
instance5.books.push('设计模式');
console.log(instance5.books);
instance5.getName();
instance5.getTime();
var instance6 = new SubClassFour('css book', 2013);
console.log(instance6.books);
instance6.getName();
instance6.getTime();
- 毛病:父类的构造函数执行了两遍
- 干净的继承者 - 原型式继承
- 借助原型 prototype 能够依据已有的对象创立一个新的对象,
-
同时不用创立新的自定义对象类型
function inheritObject(o) {// 申明一个过滤函数对象 function F() { } // 过滤对象的原型继承父对象 F.prototype = o; // 返回过渡对象的一个实例,改实例的原型继承了父队象 return new F();} var book5 = { name: 'js book', alikeBook: ['css book', 'html book'] }; var newBook = inheritObject(book5); newBook.name = 'ajax book';newBook.alikeBook.push('xml book'); var otherBook = inheritObject(book5); otherBook.name = 'flash book';otherBook.alikeBook.push('as book'); console.log(newBook.name); //ajax book console.log(newBook.alikeBook);//["css book", "html book", "xml book", "as book"] console.log(otherBook.name);//flash book console.log(otherBook.alikeBook);// ["css book", "html book", "xml book", "as book"] console.log(book5.name);//js book console.log(book5.alikeBook);//["css book", "html book", "xml book", "as book"]
锦上添花 – 寄生式继承
// 寄生式继承
// 申明基对象
var book6 = { name: 'js book',
alikeBook: ['css book', 'html book']
};
// 原型式继承
function inheritObjectTwo(o) {// 申明一个过滤函数对象 function F() { }
// 过滤对象的原型继承父对象 F.prototype = o; // 返回过渡对象的一个实例,改实例的原型继承了父队象 return new F();}
function createBook(obj) {console.log(obj);
// 通过原型继承形式创立新对象 var o = inheritObjectTwo(obj);
console.log(o.name);
// 拓展新对象 o.getName = function () { console.log(this.name);
}; // 返回拓展后的新对象 return o;}
var book7 = createBook(book6);
console.log(book7.getName);
终极继承者
/*
* 寄生式继承 继承原型 * 传递参数 subClass 子类 * 传递参数 superClass 父类 * constructor 属性返回对创立此对象的数组函数的援用。* */function inheritPrototype(subClass, superClass) {// 复制一份父类的原型正本保留在变量中 var p = inheritObject(superClass.prototype);
// 修改因为重写子类原型导致子类的 constructor 属性被批改 p.constructor = subClass; // 设置子类的原型 subClass.prototype = p;}
// 定义父类
function ParentClass(name) {this.name = name; this.colors = ['red', 'blue', 'green']}
// 定义父类原型办法
ParentClass.prototype.getName = function () { console.log(this.name);
};
// 定义子类
function ChildClass(name, time) {// 构造函数式继承 ParentClass.call(this, name);
// 子类新增属性 this.time = time;}
// 寄生式继承父类原型
inheritPrototype(ChildClass, ParentClass);
// 子类新增原型办法
ChildClass.prototype.getTime = function () { console.log(this.time);
};
// 创立两个测试方法
var test1 = new ChildClass('js book', 2014);
var test2 = new ChildClass('css book', 2013);
test1.colors.push('black');
console.log(test1.colors);//["red", "blue", "green", "black"]
console.log(test2.colors);//["red", "blue", "green"]
test2.getName();//css book
test2.getTime();//2013
老师不止一位 – 多继承
// 单继承 属性复制
var extend = function (target, source) {// 遍历原对象中的属性 for (var property in source) {target[property] = source[property]; } // 返回指标对象 return target;};
// 多继承 属性复制
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 上,这样所有的对象就能够领有这个办法 * */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]; } }};
多种调用形式 — 多态
依据参数数量的不同 运行不同的程序
// 多态
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]; }}
原文