最佳实践:
(1) 定义基类,在基类构造函数中定义属性和私有方法,在基类的prototype中连接方法(function)
(2) 定义一个空对象F,空对象的prototype属性指向基类的prototype属性
(3) 定义子类,在子类的构造函数中调用基类的call方法
(4) 设置子类的prototype属性为(2)F的示例(new 一个 F)
具体,建下面 第3部分.
1. javascript继承,在子类的构造函数的第一行执行 基类的call方法.
//定义一个基类 function Animal() { this.species = "动物"; } //定义一个子类 function Cat(name,color) { Animal.call(this);//相当于调用基类的构造函数 this.name = name; this.color = color; } var aCat = new Cat('Tom','black'); console.log(aCat);
上面console.log(aCat);代码的输出为:
Cat {species: "动物", name: "Tom", color: "black"}
从这个输出可见这里子类正确的获得了基类的species属性.
这样做有两个问题:
(1) 基类的prototype中的属性和方法将不被继承.
(2) 基类的静态属性和方法不被继承
代码如下:
//定义一个基类 function Animal() { this.species = "动物"; } Animal.prototype.show = function() { alert('This is An Animal.');}; //定义基类一个普通方法 Animal.legCount=4; //定义动物有4条腿,类的静态属性 Animal.TestStaticFunction = function() {alert('TestStaticFunction.');};//基类,静态方法 //定义一个子类 function Cat(name,color) { Animal.call(this);//相当于调用基类的构造函数,将基类的属性继承过来,但仅限于在基类的构造函数中定义的属性 this.name = name; this.color = color; } var anAnimal = new Animal(); var aCat = new Cat('Tom','black'); console.log(Animal.legCount); //4,基类静态属性,使用类访问,正常 //console.legCount(anAnimal.legCount);//报错,静态属性只能通过类访问 Animal.TestStaticFunction(); //基类静态方法,使用类访问,正常 //anAnimal.TestStaticFunction(); //报错,静态属性只能通过类访问 console.log(aCat); console.log(aCat.legCount);//undefined,静态属性,只能通过类访问(Java中能通过实例访问静态属性) console.log(Cat.legCount); //undefined,静态属性,不能继承 //Cat.TestStaticFunction(); //报错,Cat没有从基类继承 静态方法 TestStaticFunction() anAnimal.show(); //基类prototype中方法,正常访问 //aCat.show(); //报错,没有show()方法
上面的问题(2)解决方法 参见
http://jackyin5918.iteye.com/blog/1973113
(非构造函数继承_解决Javascript不能继承基类静态方法和静态变量)
下面解决问题(1) 基类的prototype中的属性和方法将不被继承
2. 解决 基类的prototype中的属性和方法将不被继承
使用下面代码:
//定义一个基类 function Animal() { this.species = "动物"; } Animal.prototype.show = function() { alert('This is An Animal. name=' + this.name);}; //定义基类一个普通方法 Animal.legCount=4; //定义动物有4条腿,类的静态属性 Animal.TestStaticFunction = function() {alert('TestStaticFunction.');};//基类,静态方法 //定义一个子类 function Cat(name,color) { Animal.call(this);//相当于调用基类的构造函数,将基类的属性继承过来,但仅限于在基类的构造函数中定义的属性 this.name = name; this.color = color; } Cat.prototype = new Animal(); //基类的prototype指向 一个新的Animal()对象, //通过prototype链(原型链)连接到基类的prototype上,从而实现继承基类的prototype Cat.prototype.constructor = Cat; //因为每个类的prototype对象都有个constructor属性,指向类自己, //这里需要Cat.prototype其实是Animal,而Animal的constructor是指向Animal的, //造成了Cat的constructor指向了Animal,产生混乱,需要修正过来 var anAnimal = new Animal(); var aCat = new Cat('Tom','black'); console.log(aCat); anAnimal.show(); //基类prototype中方法,正常访问,(但基类中this.name未定义) aCat.show(); //正常,通过prototype方式继承了基类prototype中的方法上面代码,解决了基类prototype中方法和属性不能继承问题,但是也产生了一个新问题,
就是在定义子类的时候 调用
Cat.prototype = new Animal(); //基类的prototype指向 一个新的Animal()对象,
这一句时,生成了一个基类对象Animal(),造成了内存浪费,应该避免.
3. 优化,解决内存浪费问题
使用下面代码,基本上可以完美实现继承:
//定义一个基类 function Animal() { this.species = "动物"; } Animal.prototype.show = function() { alert('This is An Animal. name=' + this.name);}; //定义基类一个普通方法 Animal.legCount=4; //定义动物有4条腿,类的静态属性 Animal.TestStaticFunction = function() {alert('TestStaticFunction.');};//基类,静态方法 //定义一个子类 function Cat(name,color) { Animal.call(this);//相当于调用基类的构造函数,将基类的属性继承过来,但仅限于在基类的构造函数中定义的属性 this.name = name; this.color = color; } var EmptyObject = function(){}; // EmptyObject.prototype = Animal.prototype; Cat.prototype = new EmptyObject(); //修改Cat的prototype不会影响到基类的prototype Cat.prototype.constructor = Cat; //因为每个类的prototype对象都有个constructor属性,指向类自己, //这里需要Cat.prototype其实是Animal,而Animal的constructor是指向Animal的, //造成了Cat的constructor指向了Animal,产生混乱,需要修正过来 var anAnimal = new Animal(); var aCat = new Cat('Tom','black'); console.log(aCat); anAnimal.show(); //基类prototype中方法,正常访问,(但基类中this.name未定义) aCat.show(); //正常,通过prototype方式继承了基类prototype中的方法
4. 实现类继承的函数:
function extend(Child, Parent) { var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.uber = Parent.prototype; }
5. 另一种实现继承的方式--拷贝属性方式
function extend2(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } c.uber = p; }
这部分主要学习了下面两篇文章:
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html
还有参考了这个:
http://msdn.microsoft.com/zh-cn/magazine/cc163419.aspx#S4