首页 > 代码库 > 面向对象(封装、继承、多态)

面向对象(封装、继承、多态)

当我们创建对象时,一般有2种写法。1.字面量直接写   2.通过构造函数进行声明

字面量:

var student={

      name:"tom",

  age:16,

  study:function(){

    alert("study");

  }

}

构造函数

function Student(name,age){            //构造函数名一般首字母大写

  this.name=name;

  this.age=age;

  this.study=function(){

    alert("study");

  }

}

构造函数通过new语句来创建实例    var student1=new Student(“tom”,16);

构造函数也是有缺点的:构造函数每new一个实例,里面的函数就会在新的实例中重新创建。因为js中函数就是对象,所以相当于构造函数中的方法又在不断的实例化对象。

因此每个实例上的同名函数并不是同一个。

在这种情况下,我们将里面的函数拿出来并放在外面,如下:

function Student(name,age){            

  this.name=name;

  this.age=age;

  this.study=study;

}

function study(){

  alert("study");

}

这样不同实例中的同名函数就会是同一个函数。

但是将函数放在外面,就会被任意的调用,没有任何的限制。

这时就需要用到原型对象(prototype):

外面的属性、方法会通过原型属性被放入原型对象中     Student.prototype.study=function(){alert("study");}

而原型中的方法、属性也只能被对应对象的实例调用这就同样起到了封装的作用,并且封装的更好,因为对象实例可以访问原型中的属性、方法,但是无法更改他们。如果在实例中定义一个和原型属性同名的属性,那么这个属性也只是覆盖了原型属性(这算是一种多态),但是原型属性并没有改变,其他实例仍然同样的调用

function Student(name){            

  this.name=name;

}

Student.prototype.age=16;

Student.prototype.study=function(){alert("study");}

var tom=new Student("tom");

var jim=new Student("jim");

tom.age=18;

alert(tom.age);   //18     这是实例自身定义的age属性

alert(jim.age);    //16     这是来自原型中age属性

(原因涉及到原型链)

继承:

构造函数中的属性、方法通过apply、call来进行继承。

原型中的属性、方法要通过原型继承

function Student(name){            

  this.name=name;

}

Student.prototype.age=16;

Student.prototype.study=function(){alert("study");}

 

function Worker(){                                         //继承Student的属性、方法

  Student.apply(this,arguments);

  this.job="XXX";                                     //再定义自身的属性

}

Worker.prototype=Student.prototype;            //继承原型的属性、方法

Worker.prototype.showjob=function(){           //定义自身的原型属性、方法

  alert(this.job);
}

面向对象(封装、继承、多态)