您的位置:首页 > 移动开发

Javascript继承机制(call、apply、prototype)

2013-07-08 09:11 579 查看
本文来自:http://blog.csdn.net/haijiaoxiaowu/article/details/5148657

Javascript的继承可以通过call、apply、prototype实现。

1、call:在子类中,用父类.call(this,arg0,arg1...)可以继承父类。注意call的位置,尽量在子类的第一行(js按顺序执行,放在后面可能对子类的其他属性、方法有影响。比如子类和父类有相同名字的方法,后面的覆盖前面的)。

[javascript]
view plaincopy

<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为参数数组)。

[javascript]
view plaincopy

<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可以为类的所有实例添加属性或方法

[javascript]
view plaincopy

<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进行联合。

[javascript]
view plaincopy

<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 父类() 来继承父类的方法。

[javascript]
view plaincopy

<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继承,类型也继承父类。详见下例

[javascript]
view plaincopy

<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> 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  call apply prototype