日期:2014-05-16  浏览次数:20310 次

使用new原理实现javascript继承
javascript的new函数与java中的new虽然同是创建对象,但是有根本的区别,java中用new创建对象时是为对象分配空间和初始化变量,而javascript使用new创建对象时实际上是先创建了一个Object对象,然后在这个对象上执行函数,例如:
var car = new Car();
相当于
var car = new Object();
Car.call(car);
通过这个原理我们可以抛弃new,然后自定义一个函数来封装创建对象的过程,从而实现继承。

构造器原理实现继承与原型继承相比较有如下优势:
1.原型继承初始化对象时父类的属性会被多次初始化;构造器原理继承只需要每个属性初始化一次,提高了性能。
2.原型继承访问对象元素时需要遍历原型链;构造器原理继承对象的所有元素和从父类中继承的元素均在当前对象上,不需要遍历原型链,提高了性能。
3.如果要在已经存在的json对象上执行类函数,原型继承需要重新创建一个对象,然后进行对象转换;构造器原理继承不需要创建新的对象,可以直接在当前对象上执行函数,提高了性能和代码灵活性。
4.原型链继承只能实现单一继承;构造器原理继承可以实现多继承,提高了代码灵活性。
5.原型链继承无法将子类构造器中的形参传给父类构造器,构造器原理继承可以将子类构造器中的形参逐层传递给父类构造器,提高了代码灵活性。
6.原型继承子类构造器会被父类覆盖,需要再手动为子类指定构造器;构造器原理继承子类和父类构造器相互独立,使用创建对象时子类构造器先调用父类构造器,更符合面向对象构造器原理。
7.子类对象调用父类set方法为属性赋值时,会在子类中重新定义一个同名属性,父类属性的原始值并没有得到真正修改;构造器原理则真正修改了从父类中继承的属性的值。

构造器原理实现继承与原型继承相比较有如下不足:
1.构造器原理的子类覆盖父类方法或属性后,该属性就会被替换,原来在父类中定义的属性或方法会被销毁,如果需要在子类中访问被覆盖的父类成员,则需要在覆盖前进行备份。如Bird.move()的实现;原型继承的子类不是替换父类的成员定义,而是在当前原型链中重新声明和定义,子类访问父类被覆盖的成员可以这样:this.contractor.prototype.move.call(this);
其中this代表当前子类。

---------------附文章源码(粘贴可运行,本机测试环境IE8)----------------
生物是基类,动物继承生物类,鸟类继承生物类

/**
* 生物体,
* 具有属性:age;
* 方法:成长;
*/
function Organism()
{
/**
* 生长,每生长一次,年龄加1
*/
this.pullulate = function()
{
this.age++ ;
};

this.getAge = function()
{
return this.age;
};

/*
* 重写toString函数
*/
this.toString = function()
{
return JSON.stringify(this);
};
};

Organism.create = function()
{
var obj = {age:0};
Organism.call(obj);
return obj;
};

/**
* 动物,生物的子类
* 属性:speed
* 方法:移动
*/
function Animal()
{
this.move = function()
{
return "moving speed:" + this.speed;
};

};
//new 原理继承
Animal.create = function(speed)
{
var obj = Organism.create();
obj.speed = speed;
Animal.call(obj);
return obj;
};

/**
* 鸟:继承动物
*/
function Bird()
{
//重写父类方法前先将父类方法备份,这样就可以调用父类方法了
var parentMove = this.move;
this.move = function()
{
//使用call在当前对象上调用父类方法
return parentMove.call(this) + "---->flying";
};

};

//new 原理继承
Bird.create = function(speed)
{
var obj = Animal.create();
obj.speed = speed;
Bird.call(obj);
return obj;
};

//原型继承
//Animal.prototype = new Organism();
//Animal.prototype.contractor = Animal;


var a1 = Animal.create(160);
var a2 = Animal.create(260);

var b1 = Bird.create(300);
var b2 = Bird.create(500);

a1.pullulate();
a1.pullulate();
a2.pullulate();

document.write('a1 age=' + a1.getAge()) ;
document.write('<br>');
document.write('a2 age=' + a2.getAge()) ;
document.write('<br>');

document.write('a1 : ' + a1.move()) ;
document.write('<br>');
document.write('a2 : ' + a2.move()) ;
document.write('<br>');

document.write('b1 : ' + b1.move()) ;
document.write('<br>');
document.write('b2 : ' + b2.move()) ;
document.write('<br>');

b2.pullulate();b2.pullulate();b2.pullulate();
document.write('b2 : ' + b2) ;

var o1 = {a:20};
var o2 = o1;
o2.a = 30;
document.write(o1.a + "" + o2.a);