JS面向对象高级


原型链继承-prototype属性

常见方法
Student.prototype=new Person();
Student的prototype指向一个Person的实例,所有“学生”的实例,就能继承Person了
注意:
如果替换了prototype对象:o.prototype={};要为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数:o.prototype.constructor=o;

原型链继承prototype属性实例:
function Per1(){
this.foot=2;
this.head=1;
}
function Stu1(name,no){
this.name=name;
this.no=no;
}
Stu1.prototype=new Per1();//通过prototype属性实现继承
//Stu1的prototype属性指向一个Per1实例的写法,相当于完全删除了prototype原先的值,赋了一个新值
//手工理顺继承链
Stu1.prototype.constructor=Stu1;
//每个实例的prototype对象都有一个construction属性
// alert(Stu1.prototype.constructor);
var stue=new Stu1(‘张三’,’001’);
alert(stue.constructor);//继承链紊乱
alert(stue.name);
alert(stue.no);
alert(stue.foot);
alert(stue.head);

原型链继承-直接继承prototype

对上一种方法的改进
由于Person对象中,不变的属性都可以直接写入Person.prototype,所以可以让Student()跳过Person(),直接继承Person.prototype
优点:
效率比较高,不用执行和建立Person的实例
缺点:
Student.prototype和Person.prototype现在指向了同一个对象,任何对Student.prototype的修改,都会反映到Person.prototype

原型链直接继承prototype属性实例:
function Per1(){
}
Per1.prototype.foot=2;
Per1.prototype.head=1;
function Stu1(name,no){
this.name=name;
this.no=no;
}

//通过直接继承prototype属性实现继承
//优点,相较于第一种,不用执行和建立Per1实例,节省内存
//缺点,把父类Per1的construction也同步改掉了
// alert(Per1.prototype.constructor);
Stu1.prototype=Per1.prototype;
//手工理顺继承链
Stu1.prototype.constructor=Stu1;
//每个实例的prototype对象都有一个construction属性
// alert(Stu1.prototype.constructor);
var stue=new Stu1(‘张三’,’001’);
// alert(stue.constructor);//继承链紊乱
// alert(stue.name);
// alert(stue.no);
// alert(stue.foot);
// alert(stue.head);

利用空对象作为中介

空对象几乎不占内存
修改Student的prototype对象,不会影响Person的prototype对象可以封装函数

实例:
function Per1(){
}
Per1.prototype.foot=2;
Per1.prototype.head=1;
function Stu1(name,no){
this.name=name;
this.no=no;
}

//定义一个空对象,几乎不占内存
var F=function(){};
F.prototype=Per1.prototype;
Stu1.prototype=new F();
//以上写法固定写法
//缺点,把父类Per1的construction也同步改掉了
//F空对象作为中介解决了以上缺点
// alert(Per1.prototype.constructor);
var stue=new Stu1(‘张三’,’001’);
Stu1.prototype.constructor=Stu1;
// alert(stue.constructor);//继承链紊乱
// alert(stue.name);
// alert(stue.no);
// alert(stue.foot);
// alert(stue.head);

使用空对象作为中介封装函数实例:
function Per1(){
}
Per1.prototype.foot=2;
Per1.prototype.head=1;
function Stu1(name,no){
this.name=name;
this.no=no;
}
//空对象作为中介完成继承
function ext(Child,Par){
var F=function(){};
F.prototype=Par.prototype;
Child.prototype=new F();
Child.prototype.constructor=Child;
}
ext(Stu1,Per1);

//缺点,把父类Per1的construction也同步改掉了
//F空对象作为中介解决了以上缺点
// alert(Per1.prototype.constructor);
var stue=new Stu1(‘张三’,’001’);
Stu1.prototype.constructor=Stu1;
alert(stue.constructor);//继承链紊乱
// alert(stue.name);
// alert(stue.no);
// alert(stue.foot);
// alert(stue.head);

构造函数绑定

在子类型构造函数的内部调用父类型构造函数通过call()或apply()方法
function.call(thisObj[,arg1[,arg2[,[,…argN]]]])调用一个对象的一个方法,以另一个对象替换当前对象。例如:B.call(A,args1,args2);即A对象调用B对象的方法
function.apply(thisObj[,argArray])应用某一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A,arguments);即A对象应用B对象的方法
两方法产生的作用相同,传参不同

call和apply实例:
function Per1(){
this.foot=2;
this.head=1;
this.favorColor=[‘red’,’yellow’];
}
function Stu1(name,no){
//将父对象的构造函数绑定到子对象上面
//‘借调’父类的构造函数
// Per1.call(this);
Per1.apply(this);
this.name=name;
this.no=no;
}
//Stu1的prototype属性指向一个Per1实例的写法,相当于完全删除了prototype原先的值,赋了一个新值
Stu1.prototype=new Per1();
Stu1.prototype.constructor=Stu1;
var stue=new Stu1(‘张三’,’001’);
stue.favorColor.push(‘blue’);
// alert(stue.foot);
// alert(stue.head);
// alert(stue.favorColor);
// var stue2=new Stu1(‘李四’,’002’);
// alert(stue2.favorColor);

call与apply的区别实例:call传参数逗号隔开,apply传参数数组

function Per1(addre,sex){
this.foot=2;
this.head=1;
this.addre=addre;
this.sex=sex;
}
function Stu1(name,no){
//使用call,apply实现继承
// Per1.call(this,’北京’,’女’);
Per1.apply(this,[‘北京’,’女’]);
this.name=name;
this.no=no;
}
var stue3=new Stu1(‘张三’,’004’);
// alert(stue3.foot);
// alert(stue3.head);
// alert(stue3.addre);
// alert(stue3.sex);

组合继承

将原型链继承和构造函数继承组合在一块
原型链实现对原型属性和方法的继承
借用构造函数实现对实例属性的继承

组合继承实例:
function Per1(){
this.foot=2;
this.head=1;
this.favorColor=[‘red’,’yellow’];
}
Per1.prototype.sayColor=function(){
alert(‘hello’+this.favorColor);
}
function Stu1(name,no){
//使用构造函数绑定实现对父类属性的继承
Per1.call(this);
this.name=name;
this.no=no;
}
//原型链继承-继承prototype对象的属性和方法
Stu1.prototype=new Per1();
Stu1.prototype.constructor=Stu1;
var stue4=new Stu1(‘张三’,’005’);
// alert(stue4.foot);
// alert(stue4.head);
// alert(stue4.favorColor);
var stue5=new Stu1(‘李四’,’008’);
// alert(stue5.foot);
// alert(stue5.head);
// alert(stue5.favorColor);

拷贝继承

把父对象的所以属性和方法拷贝进子对象
把父对象的prototype对象中的属性一一拷贝给Child对象的prototype对象

拷贝继承实例:
function Per1(){}
Per1.prototype.foot=2;
Per1.prototype.head=1;
Per1.prototype.sayse=function(){
alert(‘hello’+this.foot+’脚’+this.head+’头’);
}
function Stu1(name,no){
this.name=name;
this.no=no;
}
//拷贝继承
function ett(Child,Par){
var p=Par.prototype;
var c=Child.prototype;
for(i in p){
c[i]=p[i];
}
}
ett(Stu1,Per1);
var stue6=new Stu1(‘王麻子’,’007’);
// alert(stue6.foot);
// alert(stue6.head);
// alert(stue6.name);
// alert(stue6.no);
stue6.sayse();


文章作者: COOL
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 COOL !
评论
  目录