首页 > 代码库 > javascript面向对象程序设计——继承初步(by vczero)

javascript面向对象程序设计——继承初步(by vczero)

上一篇说了javascript的封装,没有刻意去说javascript的“共有函数”、“私有函数”,因为个人觉得这只是作用域的问题,我们不能刻意的模仿强类型语言(C++/JAVA)而去编写代码。尊重每一门语言的特性才是最为重要的。

一、基于prototype原型的继承

 1 var Person = function(name, age){ 2         this.name = name; 3         this.age = age; 4     } 5  6     Person.prototype = { 7         addUser: function(){ 8             console.log(‘用户:‘ + this.name + ‘已添加‘); 9         },10 11         getName: function(){12             return this.name;13         }14     }15 16     Person.getUser = function(user){17         console.log(user.name + ‘已经找到‘);18     }19 20     var p = new Person(‘山鬼谣‘, 30);21     console.log(p.name);//山鬼谣22     p.addUser();//用户:山鬼谣已经添加23     Person.getUser(p); //山鬼谣已经找到

这时,我们看到《侠岚》中的游不动(人名)也出现了,但是游不动是最为基本的侠岚(四象侠岚),因此游不动具有自己的个性特征。因此,我们需要构建四象侠岚的类SiXiang,但是四象侠岚又具备最基本的Person特性,因此继承于Person。

 1     var Sixiang = function(name, age, tech){ 2         this.name  = name; 3         this.age = age; 4         this.tech = tech; 5     } 6  7     Sixiang.prototype = new Person(); 8     Sixiang.prototype.showTech = function(){ 9         console.log(‘我的技能是:‘ + this.tech);10     }11 12     var youbudong = new Sixiang(‘游不动‘, 18, ‘土‘);13     console.log(youbudong.name);//游不动14     youbudong.addUser();//用户:游不动已经添加15     console.log(youbudong.getName());//游不动16     youbudong.showTech();//我的技能是:土17     //静态方法是不能被继承的,因为Sixiang.prototype接收的是一个实例18     //youbudong.getUser(youbudong); //has no method getUser

我们可以看到通过原型的继承,因为是new一个实例赋给了子类的prototype,因此,子类子包含父类实例的方法,而不含类方法(静态方法)。如果子类中定义了与父类中原型一样的方法,将会覆盖父类的方法如,新增Sixiang.prototype.getName方法:

 1     var Sixiang = function(name, age, tech){ 2         this.name  = name; 3         this.age = age; 4         this.tech = tech; 5     } 6  7     Sixiang.prototype = new Person(); 8     Sixiang.prototype.showTech = function(){ 9         console.log(‘我的技能是:‘ + this.tech);10     }11 12     Sixiang.prototype.getName = function(){13         return ‘四象侠岚的getName方法‘;14     }15 16     var youbudong = new Sixiang(‘游不动‘, 18, ‘土‘);17     console.log(youbudong.name);//游不动18     youbudong.addUser();//用户:游不动已经添加19     console.log(youbudong.getName());//四象侠岚的getName方法20     youbudong.showTech();//我的技能是:土21     //静态方法是不能被继承的,因为Sixiang.prototype接收的是一个实例22     //youbudong.getUser(youbudong); //has no method getUser

二、构造函数指向问题
我们可以测试下以下代码,发现Sixiang的构造函数指向有问题。

console.log(youbudong.constructor === Sixiang);//falseconsole.log(youbudong.constructor === Person);//false

这不对啊,为什么既不是父类的构造函数又不是子类的呢。将子类整理以下,我们将代码拷贝到chrome的console中看看,发现:

 1 var Sixiang = function(name, age, tech){ 2         this.name  = name; 3         this.age = age; 4         this.tech = tech; 5     } 6  7     Sixiang.prototype = new Person(); 8     Sixiang.prototype.showTech = function(){ 9         console.log(‘我的技能是:‘ + this.tech);10     }11 12     var youbudong = new Sixiang(‘游不动‘, 18, ‘土‘);13     console.log(youbudong.name);//游不动14     youbudong.addUser();//用户:游不动已经添加15     console.log(youbudong.getName());//四象侠岚的getName方法16     youbudong.showTech();//我的技能是:土17     console.log(youbudong);

我们在var youbudong = new Sixiang(‘游不动‘, 18, ‘土‘);前添加Sixiang.prototype.constructor = Sixiang;我们再到chrome看。

 1     var Sixiang = function(name, age, tech){ 2         this.name  = name; 3         this.age = age; 4         this.tech = tech; 5     } 6  7     Sixiang.prototype = new Person(); 8     Sixiang.prototype.showTech = function(){ 9         console.log(‘我的技能是:‘ + this.tech);10     }11     Sixiang.prototype.constructor = Sixiang;12     var youbudong = new Sixiang(‘游不动‘, 18, ‘土‘);13     console.log(youbudong.name);//游不动14     youbudong.addUser();//用户:游不动已经添加15     console.log(youbudong.getName());//四象侠岚的getName方法16     youbudong.showTech();//我的技能是:土17     console.log(youbudong);18     console.log(youbudong.constructor === Sixiang);//true

这样,构造函数的指向问题得以修正。下一篇,重点介绍原型链和封装类的继承。