JS 继承机制的设计思想Brendan Eich,
new 构造函数缺点:
引入 prototype 属性,
JS 继承机制的设计思想,
JS 面向对象--封装1. 生成实例对象的原始模式var cat = {
name: '',
color: ''
}
// ------------------------
var cat1 = {};
cat1.name = 'Kitty';
cat1.color = 'yellow';
var cat2 = {};
cat1.name = 'Lucy';
cat1.color = 'black';
缺点,
2. 原始模式的改进解决了代码重复, function Cat(name, color) {
return {
name: name,
color: color
}
}
var cat1 = Cat('Kitty', 'yellow');
var cat2 = Cat('Lucy', 'black');
缺点,
3. 构造函数模式为了解决从源性对象生成实例的问题,JS 提供了一个构造函数(Constructor)模式。 构造函数,
function Cat(name, color) {
this.name = name;
this.color = color;
}
var cat1 = new Cat('Kitty', 'yellow');
var cat2 = new Cat('Lucy', 'black');
至此,
console.log(cat1.constructor == Cat); // true
console.log(cat2.constructor == Cat); // true
console.log(cat1 instanceof Cat); // true
console.log(cat2 instanceof Cat); // true
缺点,
4. prototype 模式JS 规定,
function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype.eat = function() {
alert('eating mouse...');
}
var cat1 = new Cat('Kitty', 'yellow');
var cat2 = new Cat('Lucy', 'black');
cat1.eat(); // eating mouse...
cat2.eat(); // eating mouse...
至此,
5. prototype 模式的验证方法
// isPrototypeOf
console.log(Cat.prototype.isPrototypeOf(cat1)); // true
console.log(Cat.prototype.isPrototypeOf(cat2)); // true
// hasOwnProperty
console.log(cat1.hasOwnProperty('name')); // true
console.log(cat2.hasOwnProperty('type')); // false
// in
console.log('name' in cat1); // true
console.log('type' in cat1); // false
// 遍历属性
for(var prop in cat1) {
console.log('cat1[' prop ']=' cat1[prop]);
}
JS 面向对象--继承:构造函数的继承对象之间的“继承”的 5 种方法, // 两个构造函数
// 动物对象的构造函数
function Animal() {
this.species = '动物';
}
// 猫对象的构造函数
function Cat(name, color) {
this.name = name;
this.color = color;
}
怎样才能使 1. 构造函数绑定最简单的方法,使用 function Cat(name, color) {
Animal.apply(this, arguments); // 父对象的构造函数绑定到子对象上
this.name = name;
this.color = color;
}
var cat1 = new Cat('Kitty', 'yellow');
alert(cat1.species); // 动物
2. prototype 模式最常见的方法,使用 如果 Cat.prototype = new Animal(); // 猫的 prototype 指向 Animal 的实例
Cat.prototype.constructor = Cat; // 别忘了把构造函数的指向恢复成 Cat 哦
var cat1 = new Cat;
alert(cat1.species); // 动物
编程时务必注意,
o.prototype = {}; // o 的 prototype对象 被新的对象{} 替换了
o.prototype.constructor = o; // 必须将新的 prototype 对象加上 constructor 属性,指回原来的构造函数
3. 直接继承 prototype这是对第二种方法的改进,
// 改写 Animal 对象
function Animal() {};
Animal.prototype.species = '动物';
Cat.prototype = Animal.prototype; // 将 Cat的prototype对象直接指向Animal的prototype对象,就完成了继承
Cat.prototype.constructor = Cat; // 这一步,实际上把 Animal.prototype对象的constructor属性也改掉了
var cat1 = new Cat('Kitty', 'yellow');
alert(cat1.species); // 动物
与第二种比,
4. 利用空对象作为中介怎么解决上面的缺点? 可以用空对象作为中介。 var F = function() {}; // 空对象
F.prototype = Animal.prototype; // 空对象的原型指向动物的原型
Cat.prototype = new F(); // 原型指向新的实例对象,空对象几乎不占内存哦
Cat.prototype.constructor = Cat;// 此时,修改Cat的prototype对象,就不会影响到Animal的prototype对象
alert(Animal.prototype.constructor); // Animal
将上面的方法,封装成一个函数,便于使用。 function extend(Child, Parent) {
var F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype; // 为子对象设一个uber属性,这个属性直接指父对象的prototype属性,等于在子对象可以直接调用父对象的方法。只是为了实现继承的完备性,纯属备用性质。
}
// 使用的时候,方法如下
extend(Cat, Animal);
var cat1 = new Cat('Kitty', 'yellow');
alert(cat1.species); // 动物
5. 拷贝继承上面是采用 prototype对象,实现继承。 换一种思路,纯粹采用”拷贝“方法实现继承,把父对象的所有属性和方法,拷贝进子对象,不也能够实现继承吗?
function Animal() {};
Animal.prototype.species = '动物';
function extend2(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for(var i in p) {
c[i] = p[i]; // 将父对象的属性一一拷贝给Child对象的prototype对象
}
c.uber = p;
}
// 使用的时候
extend2(Cat, Animal);
var cat1 = new Cat('Kitty', 'yellow');
alert(cat1.species); // 动物
JS 面向对象--继承: 非构造函数的继承1. 什么是”非构造函数“的继承var Chinese = {
nation: '中国'
};
var Doctor = {
career: '医生'
}
// 怎么样才能让 Doctor 去继承 Chinese 呢 ??
// 两个都是普通对象,不是构造函数,无法使用构造函数方法实现”继承“
2. object() 方法json格式的发明人Douglas Crockford,提出了一个 function object(o) {
function F() {}
F.prototype = o; // object()函数,其实只做一件事,就是把子对象的prototype属性指向父对象,从而使得子对象与父对象连在一起
return new F();
}
// 使用的时候:
// 第一步,先在父对象的基础上,生成子对象;
var Doctor = object(Chinese);
// 然后,再加上子对象本身的属性:
Doctor.career = '医生';
// 这时,子对象已经继承了父对象的属性了
alert(Doctory.nation); // 中国
3. 浅拷贝// 浅拷贝
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
return c;
}
// 使用
var Doctor = extendCopy(Chinese);
Doctor.career = '医生';
alert(Doctor.nation); // 中国
缺点,
4. 深拷贝所谓 深拷贝,就是能够实现真正意义上的数组和对象的拷贝。只要递归调用 浅拷贝就行了。 function deepCopy(p, c) {
var c = c || {};
for (var i in p) {
if(typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
}else {
c[i] = p[i];
}
}
return c;
}
// 使用
var Doctor = deepCopy(Chinese);
因为是值的深度拷贝,所以父对象不会收到影响。jQurey库目前使用的继承方法。 说明:以上皆为个人精简笔记 |
|
来自: 昵称35438912 > 《待分类》