要注意复制引用。
很烦的是,在复制引用的时候,有的时候并不是期望的结果。
让我们创建两个构造函数,给prototype添加属性
var A = function(){},B=function(){}; A.prototype.stuff=[1,2,3];//[1,2,3] A.prototype.name='a';//a
让我们用B继承A,
extend2(B, A);
用extend2的方法,B的prototype继承A的prototype属性。
B.prototype.hasOwnProperty('name');//true B.prototype.hasOwnProperty('stuff');//true
name属性是一个基本类型的复制,stuff属性是一个引用的复制。让我们看看如下代码
B.prototype.stuff;//[1,2,3] B.prototype.stuff===A.prototype.stuff;//true //改变B的name,并不会影响A B.prototype.name+='b';//ab A.prototype.name//a
当改变B的stuff属性时候,也会影响A的stuff属性。
但是如果你用另一个对象去覆盖了B.prototype,下列代码A指向了旧的对象,B指向了新的对象。
B.prototype.stuff = ['a', 'b', 'c'];//["a","b","c"] A.prototype.stuff;//[1,2,3,4,5,6]
对象继承对象
前面所说的继承都是用构造函数创建的对象,我们可以用一个构造函数创建的对象去继承另一个构造函数创建的对象,然而也可以用对象文字量(object literal)去使用继承.
在java中,可以定义一个类去继承另一个类,因为类有面向对象的基本功能。在javascript并没有类,所以我们用构造函数去模拟,另外也提供了new操作符。让我们看如下代码
Child.prototype = new Parent();
Child构造函数继承与Parent,但是它紧紧继承于new Parent。看起来虽然像类继承,但是这并不是类继承。
像前面所说的属性复制继承方式,就是把一个对象的所有属性拷贝到另一个对象中。
对象可以var o={}的方式创建,这样也可以把其他对象的属性拷贝至这个对象中,代码如下:
function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } c.uber = p; return c; }
简单的属性复制是很简单的方式,有许多开源项目都这么使用继承的。如Jquery,firebug.
让我我们看一个简单的例子。
var shape = { name: 'shape', toString: function() {return this.name;} }
创建一个基于shape的对象我们可以用extendCopy的方式,这就就可以扩展子对象的功能了。
var twoDee = extendCopy(shape); twoDee.name = '2D shape'; twoDee.toString = function(){return this.uber.toString() + ', ' + this.name;};
triangle继承2D shape 对象。
var triangle = extendCopy(twoDee); triangle.name = 'Triangle'; triangle.getArea = function(){return this.side * this.height / 2;}
调用triangle
triangle.side = 5; triangle.height = 10; triangle.getArea();//25 triangle.toString();// "shape, 2D shape, Triangle"
一点说明,这里的
triangle.side = 5; triangle.height = 10;
可以用构造方法(这里叫方法,就像Java的类中的"函数")来赋值。可以在这个构造函数中调用一个init(side,height)来赋值初始化,很方便。