本文来自:http://blog.csdn.net/haijiaoxiaowu/article/details/5148657
Javascript的继承可以通过call、apply、prototype实现。
1、call:在子类中,用父类.call(this,arg0,arg1...)可以继承父类。注意call的位置,尽量在子类的第一行(js按顺序执行,放在后面可能对子类的其他属性、方法有影响。比如子类和父类有相同名字的方法,后面的覆盖前面的)。
- <html>
- <head>
- <title>call/apply/prototype test</title>
- </head>
- <script type="text/javascript">
- //person类
- function person(name, age) {
- this.name = name;
- this.age = age;
- this.say = function() {
- document.write("I am a person");
- }
- this.display = function() {
- document.write(this.name + "-" + this.age);
- }
- }
- //student类,继承自person
- function student(name, age, no) {
- person.call(this, name, age);//person中的this等于参数中的this,即student中的name和age
- this.no = no;
- this.display = function() {//覆盖了父类的方法
- document.write(this.name + "-" + this.age + "-" + this.no);
- }
- }
- //创建person类
- var p = new person("captain", 21);
- p.display();//captain-21
- p.say();//I am a person
- //创建student类
- var s = new student("captain", 21, "06281097")
- s.display();//captain-21-06281097
- s.say();//I am a person 继承了父类的方法
- <script>
- <body>
- </body>
- </html>
2、apply:在子类中,用父类.apply(this,args)可以继承父类(args为参数数组)。
- <html>
- <head>
- <title>call/apply/prototype test</title>
- </head>
- <script type="text/javascript">
- //person类
- function person(name, age) {
- this.name = name;
- this.age = age;
- this.say = function() {
- document.write("I am a person");
- }
- this.display = function() {
- document.write(this.name + "-" + this.age);
- }
- }
- //student类,继承自person
- function student(name, age, no) {
- person.apply(this, new Array(name, age));//与call不同的是,apply传递的是数组
- this.no = no;
- this.display = function() {//覆盖了父类的方法
- document.write(this.name + "-" + this.age + "-" + this.no);
- }
- }
- //创建person类
- var p = new person("captain", 21);
- p.display();//captain-21
- p.say();//I am a person
- //创建student类
- var s = new student("captain", 21, "06281097")
- s.display();//captain-21-06281097
- s.say();//I am a person 继承了父类的方法
- <script>
- <body>
- </body>
- </html>
3、prototype:类.prototype可以为类的所有实例添加属性或方法
- <html>
- <head>
- <title>call/apply/prototype test</title>
- </head>
- <script type="text/javascript">
- //定义学生类(姓名、学好、年龄)
- function student(name, no, age) {
- this.name = name;
- this.no = no;
- this.age = age;
- }
- //学生实例
- var captain = new student("captain", "06281097", 21);
- //添加学校属性
- student.prototype.school = null;
- //为captain学生的学校属性赋值
- captain.school = "BJTU";
- //显示captain的学校
- document.write(captain.school);
- <script>
- <body>
- </body>
- </html>
可见,通过prototype为类添加属性是不方便的,因为构造函数已经固定,实例化时无法对新加入的属性进行初始化。比如上例中的school属性,在新建student对象时,无法通过new student(name,no,age,school)进行初始化,很不方便。所以一般都用prototype为类添加方法。
使用prototype进行继承时,还存在着一些问题,比如下例中的student.prototype=new person();这里无法加入参数,因为一旦加入参数则所有的student实例的name和age都是固定的值。这种情况下就需要用call和prototype进行联合。
- <script type="text/javascript">
- //person类
- function person(name, age) {
- this.name = name;
- this.age = age;
- this.say = function() {
- document.write("I am a person");
- }
- this.display = function() {
- document.write(this.name + "-" + this.age);
- }
- }
- //student类
- function student(name, age, no) {
- this.no = no;
- this.display = function() {//覆盖了父类的方法
- document.write(this.name + "-" + this.age + "-" + this.no);
- }
- }
- student.prototype = new person();//student继承person(无法写带参构造函数)
- //student.prototype = new person("name","age");//所有student实例的姓名都为name,年龄是age
- var s = new student("captain", 21, "06281097");
- s.say();//I am a person
- s.display();//undefined-undefined-06281097
- //student的name、age没有从参数中获得(两个属性要在person的构造行数中获得,但是prototype的构造函数无参)
- <script>
4、call和prototype联合:解决了使用prototype不能使用带参构造函数的问题。在父类中,只定义属性字段,通过prototype为类添加方法。在子类中,通过call来调用父类带参构造函数,通过 子类.prototype=new 父类() 来继承父类的方法。
- <script type="text/javascript">
- //person类
- function person(name, age) {
- this.name = name;
- this.age = age;
- }
- person.prototype.say = function() {//为person类添加say方法
- document.write("I am a person");
- };
- person.prototype.display = function() {//为person类添加display方法
- document.write(this.name + "-" + this.age);
- };
- //student类
- function student(name, age, no) {
- person.call(this,name,age);//可以获得父类构造方法(this.name=name;this.age=age;)
- this.no = no;
- }
- student.prototype = new person();//没有此句,student类无法获得person的say/display方法
- student.prototype.display = function() {//为student类添加display方法,并覆盖了父类的方法
- document.write(this.name + "-" + this.age + "-" + this.no);
- };
- var s = new student("captain", 21, "06281097");
- s.say();//I am a person
- s.display();//captain-21-06281097
- <script>
5、继承之后的类型:用call继承,类型并没有发生变化;用prototype继承,类型也继承父类。详见下例
- <script type="text/javascript">
- //person类
- function person(name, age) {
- this.name = name;
- this.age = age;
- }
- //student类,继承自person(call)
- function student(name, age, no) {
- person.call(this, name, age);
- this.no = no;
- }
- //programer类,继承自person(prototype)
- function programer(name, age, sex) {
- this.sex = sex;
- }
- programer.prototype = new person();
- //man类,继承自person(prototype)
- function man(name, age, height) {
- person.call(this, name, age);
- this.height = height;
- this
- }
- man.prototype.say = function() {
- alert(this.name);
- };
- //创建person实例
- var p = new person("captain", 21);
- //创建student实例
- var s = new student("captain", 21, "06281097");
- //创建programer实例
- var g = new programer("captain", 21, "男");
- //创建man实例
- var m = new man("captain", 21, 176);
- //判断类型(typeof返回全是object,所以用instanceof)
- alert(s instanceof person);//false 使用call并不是完全的继承
- alert(s instanceof student);//true
- alert(g instanceof person);//true
- alert(g instanceof programer);//true
- alert(m instanceof person);//false
- //只有使用prototype添加父类的构造函数,才能在意义上完全继承person
- alert(m instanceof man);//true
- <script>