继承
继承算是Javascript里面最最最最最最难一点了,所以再怎么深入理解都不为过。
本文将继续探讨Javascript的继承。
构造函数的继承
一、 构造函数绑定
使用call( )或者apply( )
父类.call(子类, [参数])
二、prototype模式
子类的prototype对象,指向父类的实例。
语法:
子类.prototype = new 父类();
子类.prototype.constructor = 子类; // 这语句很重要!!!
Javascript神坑在这里!!!
为什么需要第二个语句呢?
任何一个子类的prototype对象都有一个constructor属性,指向它自身。
并且子类的实例也有一个constructor属性,默认调用prototype对象的constructor属性。
如果没有第二个语句
子类.prototype = new 父类();
这个语句执行以后,子类.prototype.constructor指向父类。
子类的constructor属性,也指向父类。
由此,造成继承混乱。
必须记住
如果修改了ptototype指向,必须将constructor指回自身。
空对象作中介
var F = function(){};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
这个空对象做的事有这么几件:
将自身的prototype指向
父类.prototype
子类的prototype指向空对象的实例
修正子类的.prototype.constructor为子类自身
拷贝继承
父类的所有不变的属性和方法,都放到它的prototype对象上。
function extend(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
}
非构造函数的继承
非构造函数,也就是连个普通的函数。
object()方法
function object(parent) {
function F() {}
F.prototype = parent;
return new F();
}
//使用
var Tim = object(Person);
这个object()函数,其实只做一件事,就是把子对象的prototype属性,指向父对象。
浅拷贝
缺点:
不能实现数组或对象的拷贝。
如果父对象的属性等于数组或另一个对象,浅拷贝的实质是获得父类指向的地址,而不是拷贝成自身的属性!
在上面的基础上,如果父类改变了,子类也会随之改变。
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
return c;
}
深拷贝
可以实现数组和对象的拷贝。
实质上就是递归地调用浅拷贝。
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;
}
本文总结自:
阮一峰
Javascript面向对象编程(一)
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html
Javascript面向对象编程(二)
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
Javascript面向对象编程(三)
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html
内容版权原作者所有,仅作整理之用。