ECMAScript-12 【继承深入-call-apply-圣杯模式-模块化-常见继承方式】

一.继承深入

(1).继承概念

function Person(){
    
}
Person.prototype.name='Lucy';
var p=new Person();

p的name属性是继承于Pearson的,一个构造函数的原型属性是他这个构造函数构造出来的所有对象的公共祖先

(2).继承原型

Professor.prototype={
    name:'ZZa',
    tSkill:'JAVA'
}
function Professor(){}
var professor=new Professor();
Teacher.prototype=professor;
function Teacher(){
    this.name='prc',
    this.mSkill='JS/JQ'
}
var teacher=new Teacher();
console.log(teacher);

结果:

此处Teacher被实例化后将自己的原型变为了Professor的实例化对象,但是Professor的实例化对象中什么都没有,但是其中有Professor的原型,所以继承了Professor原型中的属性,而Professor的原型上又有Object原型

可以看到Teacher的_proto_中只有_proto_(Professor的原型)因为自己的构造函数中没有属性

二.call/apply

apply访问不到实例化父级的原型,但是可以访问到父级的属性和方法

所以只能说是借用别人的属性和方法不能说继承

三.圣杯模式

(1).访问父级实例化对象的属性和方法

var teacher=new Teacher();
Student.prototype=teacher;

这样既能继承实例化对象的属性和方法,也能继承原型

Student.prototype=Teacher.prototype;
Student.prototype.age=18;

这样只能继承原型,无法继承实例化对象的属性和方法

但是这样的话不仅Student的原型更改age了Teacher的也更改了

call只能继承到父级的属性和方法,继承不到原型

(2).Buffer缓冲

function Teacher(){
    this.name='Mr.Li';
    this.tSkill='JAVA';
}
Teacher.prototype={
    pskill:'JS/JQ'
}
var t=new Teacher();
function Student(){
    this.name='Mr.wang';
}
function Buffer(){}
Buffer.prototype=Teacher.prototype;
var buffer=new Buffer();
Student.prototype=buffer;
Student.prototype.age=18;
var s=new Student();
console.log(s);

结果:

uploading.4e448015.gif转存失败重新上传取消

可以看到Teacher的原型对象中没有变更 而Studet中增加了age

这样就完成了继承和隔离的问题

(3).css圣杯 双飞翼

uploading.4e448015.gif转存失败重新上传取消

<style>
			.clear::after{
				content: "";
				clear: both;
				display: table;
			}
			.wrap{
				width: 700px;
				margin:  0 auto;
				border: 1px solid #000;
			}
			.top,.foot{
				height: 50px;
				background-color: #f60;
			}
			.main{
				padding: 0 100px;
				overflow: hidden;
			}
			.main .left,
			.main .right,
			.main .content{
				float: left;
				position: relative;
				background-color: aqua;
				margin-bottom:-4000px;
				padding-bottom:4000px;
			}
			.main .content{
				margin-left: -100px;
				width: 100%;
				background-color: #e5e5e5;
				
			}
			.main .left{
				left: -100px;
				width: 100px;
			}
			.main .right{
				left: 100px;
				margin-left: -100px;
				width: 100px;
			}
   </style>
   <div class="wrap">
			<div class="top"></div>
			<div class="main clear">
				<div class="left">左边</div>
				<div class="content">c<br/>中间</div>
				<div class="right">右边</div>
			</div>
			<div class="foot"></div>
		</div>

四.模块化

(1).buff模块化

function Teacher(){}
function Student(){}
function Buffer(){}
inherit(Student,Teacher);
function inherit(Target,Origin){
    function Buffer(){}
    Buffer.prototype=Origin.prototype;
    Targert.prototype=new Buffer();
    Targert.prototype.constructor=Target;//把指向改为自己
    Targert.prototype.super_class=Origin;//说明源是谁
}

(2).企业级写法(利用闭包和自执行函数)

var inherit=(function(){
     function Buffer(){}
     return function(Targert,Origin){
         Buffer.prototype=Origin.prototype;
        Targert.prototype=new Buffer();
        Targert.prototype.constructor=Targert;//把指向改为自己
        Targert.prototype.super_class=Origin;//说明源是谁
     }
})();

实例:
var inherit=(function(){
     function Buffer(){}
     return function(Targert,Origin){
         Buffer.prototype=Origin.prototype;
        Targert.prototype=new Buffer();
        Targert.prototype.constructor=Targert;//把指向改为自己
        Targert.prototype.super_class=Origin;//说明源是谁
     }
})();
var initProgrammer=(function(){
    var Programmer=function(){}
    Programmer.prototype={
        name:'程序员',
        tool:'计算机',
        say:function(){
            console.log('我是一名'+this.myName+this.name+',我的工具是:'+
            this.tool+'我的工作需要用到:'+this.lang.toString()+'。');
            
        }
    }
    function FrontEnd(){}
    function BackEnd(){}
    inherit(FrontEnd,Programmer);
    inherit(BackEnd,Programmer);
    FrontEnd.prototype.lang=['JAVA','MYSQL'];
     FrontEnd.prototype.myName='后台工程师';
      BackEnd.prototype.lang=['HTML','CSS'];
     BackEnd.prototype.myName='前端工程师';
     return {
         FrontEnd:FrontEnd,
         BackEnd:BackEnd
     }
})()
var front=new initProgrammer.FrontEnd;
front.say();
var back=new initProgrammer.BackEnd;
back.say();	

输出结果:

uploading.4e448015.gif转存失败重新上传取消

(3).企业开发模板

按需执行:
var initCompute=(function(){
    var a=1,
    b=2;
    function add(){
        return a+b;
    }
    return function(){
        add();
    }
})()
initCompute();


window.onload=function(){
    init();
}
function init(){
    initCompute();
}


插件直接执行:
;(function(){
    var Slider=function(opt){}
    Slider.prototype={}
    window.Slider=Slider
})();
var Slider=new Slider({
})

五.常见继承方式

// 定义一个动物类
function Animal (name) {
  // 属性
  this.name = name || 'Animal';
  // 实例方法
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};


//原型链继承
//父类的实例化对象赋值给子类原型
function Cat(){

}

Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
//优点:实现简单,很纯粹的继承关系
//缺点:1.在子类的原型上修改原型属性或方法得在new Animal()之后
//     2.无法实现多继承
//     3.来自原型对象的所有属性被实例化共享
//     4.创建子类时无法给父类赋值


//构造继承(call继承)
//使用父类的构造函数来增强子类实例,等于是赋值父类的实例属性给子类(没用到继承)
function Cat(){
    Animal.call(this);
}
//优点:1.来自原型对象的所有属性不会被共享
//     2.创建子类时也可给父类赋值
//     3.可以实现多继承(多call两个)
//缺点:1.实例的并不是父类的实例,只是子类的实例
//     2.只能继承父类的属性和方法,不能继承原型上的
//     3.无法实现函数复用,每个子类都有父类的实例副本,影响性能


//实例继承
//为父类添加新特性,作为子类实例返回
function Cat(){
    var instance=new Animal();
    return instance;
}
//优点:1.不限制调用方法,不管是new 还是()
//缺点:1.实例的是父类的实例,不是子类的实例
//     2.不支持多继承


//拷贝继承
function Cat(name){
  var animal = new Animal();
  for(var p in animal){
    Cat.prototype[p] = animal[p];
  }

}
//优点:1.支持多继承
//缺点:1.效率低内存占用高(要循环拷贝)
//     2.无法获取父类不可枚举的方法


//组合继承
//通过调用父类的构造,继承父类的属性和方法并保留传参的优点,然后再通过父类实例作为子类原型,实现函数复用
function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
//优点:1.弥补了构造继承的缺点,可以继承实例的属性和方法也可以继承原型的属性和方法
//      2.既是子类的实例,也是父类的实例
//      3.不存在引用属性共享的问题
//      4.可传参,函数可以复用
//缺点:1.调用了两次父类的构造函数


//寄生组合继承
//通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
//圣杯模式
(function(){
  // 创建一个没有实例方法的类
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //将实例作为子类的原型
  Cat.prototype = new Super();
})();
//就用这种

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值