JavaScrpt基础13.继承深入、call apply、圣杯模式、模块化

文章讲述了JavaScript中的原型链继承原理,通过示例展示了如何使用`call`和`apply`方法实现继承,探讨了圣杯模式及其变种,解释了闭包在封装和防止全局污染中的作用,并介绍了CSS圣杯和双飞翼布局模式。同时,文章还讨论了JavaScript的模块化开发方法,包括自启动函数和企业级的继承实现。
摘要由CSDN通过智能技术生成

13.1原型链继承

Professor.prototype = {
  name : 'Mr.Zhang',
  tSkill : 'JAVA'
}

function Professor(){}

var professor = new Professor(){};

Teacher.prototype = professor;
function Teacher(){
  this.name = 'Mr.Wang';
  this.mSkill = 'JS/JQ';
}

var teacher = new Teacher();

console.log(teacher);

image.png

    Professor.prototype = {
        name: 'Mr.Zhang',
        tSkill: 'JAVA'
    }

    function Professor(){}

    var professor = new Professor();

    // ---------------------------------
    Teacher.prototype = professor;
    function Teacher(){
        this.name = 'Joe';
        this.mSkill = 'JS/JQ';
    }

    var teacher = new Teacher();

    console.log(teacher);

    //------------------------------
    Student.prototype = teacher;
    function Student(){
        this.name = 'Lily';
        this.pSkill = 'HTML/CSS';
    }

    var student = new Student(); // student继承了上面所有原型的属性
    console.log(student);

image.png

13.2 call , apply

Teacher.prototype.wife = 'MS liu';

function Teacher(name, mSkill){
  this.name = name;
  this.mSkill = mSkill;
}

function Student(name, mSkill, age, major){
  Teacher.apply(this, [name, mSkill]); // 借用 Teacher 的属性
  this.age = age;
  this.major = major;
}

var student = new Student('Tom', 'JS/JQ', 18, 'Computer');
console.log(student);//无Teacher.prototype.wife

image.png

13.3圣杯模式

问题

// 公共原型
function Teacher(){
  this.name = 'Mr. Li';
  this.tSkill = 'JAVA';
}

Teacher.prototype = {
  pSkill: 'JS/JQ'
}
var t = new Teacher();
console.log(t);

function Student(){
  this.name = 'Mr. Wang'
}
Student.prototype = Teacher.prototype; // 继承Teacher的原型
Student.prototype.age = 18; 
// 这里更改Student的prototype,Teacher 的 prototype 也会被修改

var s = new Student();
console.log(s);

image.png

修改:圣杯模式

function Teacher(){
  this.name = 'Mr. Li';
  this.tSkill = 'JAVA';
}

Teacher.prototype = {
  pSkill: 'JS/JQ',
  obj: {a: 1}
}

var t = new Teacher();
console.log(t);

function Student(){
  this.name = 'Mr. Wang'
}

// 缓冲构造函数
function Buffer(){}

Buffer.prototype = Teacher.prototype;
var buffer = new Buffer();
console.log(buffer);

Student.prototype = buffer; 
// 相当于继承 Buffer 的原型,继承过来的东西不能修改
Student.prototype.obj.a = 4; 
// 问题:修改引用值可以修改成功,为什么❓
Student.prototype.age = 18;
// 这时候修改Student的prototype 和Teacher的prototype没有关系了

var s = new Student();
console.log(s);

image.png

封装

function Teacher(){}
function Student(){}
function Buffer(){}

inherit(Student, Teacher);

var s = new Student();
var t = new Teacher();
console.log(s);
console.log(t);

function inherit(Target, Origin){
  function Buffer(){}
  Buffer.prototype = Origin.prototype;
  Target.prototype = new Buffer(); // new 一定要放在 prototype 赋值的下方
  Target.prototype.constructor = Target; // 还原构造器
  Target.prototype.super_class = Origin; // 继承源
}

13.4CSS 圣杯模式 双飞翼

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除浮动 */
    .clearfix::after{
      content: '';
      display: table;
      clear: both;
    }

    .wrap {
      width: 700px;
      margin: 0 auto;
      border: 1px solid #000;
    }

    .top,
    .foot {
      height: 50px;
      background-color: #000;
    }

    .main {
      padding: 0 100px;
      overflow: hidden;
    }

    .main .left,
    .main .content,
    .main .right {
      float: left;
      position: relative;
      background-color: green;
      /* 圣杯模式主要逻辑是赋值 */
      margin-bottom: -2000px;  
      padding-bottom: 2000px;
    }

    .main .left {
      left: -100px;
      width: 100px;
    }

    .main .content {
      width: 100%;
      margin-left: -100px;
      background-color: red;
    }

    .main .right {
      left: 100px;
      width: 100px;
      margin-left: -100px;
    }
  </style>
</head>

<body>
  <div class="wrap">
    <div class="top"></div>
    <div class="main clearfix">
      <div class="left">123</div>
      <div class="content">234
234</div>
      <div class="right">123</div>
    </div>
    <div class="foot"></div>
  </div>
  <script type="text/javascript"></script>
</body>

</html>

image.png

13.5闭包

function test(){
    var num = 0; // 私有变量
    
    function add(){
        num++;
        console.log(num);
    }
    return add;
}

var add = test();
add();
add();
add();

以闭包的方式包装圣杯模式

1.防止对全局环境的污染
2.利于后期的开发

// 企业级写法  模块化开发
var inherit = (function test(){ 
    var Buffer = function(){}; // 有自己的命名空间了
    return function(Target, Origin){
        Buffer.prototype = Origin.prototype;
        Target.prototype = new Buffer(); // new 一定要放在 prototype 赋值的下方
        Target.prototype.constructor = Target; // 还原构造器
        Target.prototype.super_class = Origin; // 继承源
    }
})();

Teacher.prototype.name = 'Mr Zhang';

function Teacher(){}
function Student(){}
function Buffer(){}
inherit(Student, Teacher);

Student.prototype.age = 18
var s = new Student();
var t = new Teacher();
console.log(s);
console.log(t);

image.png

13.6应用

写自启动函数, 是因为加载的时候就需要启动,把里面的函数return 给变量initProgrammer保存 让initProgrammer 接收, 是因为不想里面抛出来的函数立即执行,让它等待着,等需要执行的时候再执行

var inherit = (function test(){ 
    var Buffer = function(){}; // 有自己的命名空间了
    return function(Target, Origin){
        Buffer.prototype = Origin.prototype;
        Target.prototype = new Buffer(); // new 一定要放在 prototype 赋值的下方
        Target.prototype.constructor = Target; // 还原构造器
        Target.prototype.super_class = Origin; // 继承源
    }
})();


var initProgrammer = (function(){ // 在这个函数里面造了一个伪全局,避免了全局污染
    var Programmer = function(){};
    Programmer.prototype = {
        name: '程序员',
        tool: '计算机',
        work: '编写应用程序',
        duration: '10个小时',
        say: function(){
            console.log('我是一名' + this.myName + this.name + ',我的工作是用' + this.tool + this.work + ', 我每天工作' + this.duration + ',我的工作需要用到' + this.lang.toString() + '。');
        }
    }
    function FrontEnd(){}
    function BackEnd(){}
    
    inherit(FrontEnd, Programmer);
    inherit(BackEnd, Programmer);
    
    FrontEnd.prototype.lang = ['HTML', 'CSS', 'JavaScript'];
    FrontEnd.prototype.myName = '前端';
    
    BackEnd.prototype.lang = ['Node', 'Java', 'SQL'];
    BackEnd.prototype.myName = '后端';
    
    return {
        FrontEnd: FrontEnd,
        BackEnd: BackEnd
    }
})();

var frontEnd = new initProgrammer.FrontEnd();
var backEnd = new initProgrammer.BackEnd();

frontEnd.say();
backEnd.say();

企业协同开发

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

function init(){
    initCompute();
    initFunctions();
}

// 按需启动功能
var initCompute = (function(){
    var a = 1,
        b = 2;
    function add(){
        console.log(a + b);
    }
    function minus(){
        console.log(a - b);
    }
    function mul(){
        console.log(a * b);
    }
    function div(){
        console.log(a / b);
    }
    return function(){
        add();
        minus();
        mul();
        div()
    }
})();

var initFunctions = (function(){
    
})();


// 或者用插件化开发
;(function(){
    var Slider = function(opt){}
    Slider.prototype = {
        
    }
    window.Slider = Slider;
})();

var slider = new Slider({
    
});

整合下面3个功能(模块化开发:独立的作用域空间,将抛出来的函数保存到GO)
打印100以内的能被 3 或 5 或7 整除的数
打印斐波那切数列的第n位
打印从0到一个数的累加值

window.load(){
  init();
}

function init(){
  console.log(initFb(10));  
  console.log(initDiv(100));
}


var initFb = (function(){
  function fb(n){
    if(n <= 0){
      return 0;
    }
    if(n <= 2){
      return 1;
    }
    return fb(n - 1) + fb(n - 2);
  }
  return fb;
})();

var initBiv = (function(){
  function div(n){
    for(var i = 0;i <= n; i++){
      if(i % 3 === 0 || i % 5 === 0 || i % 7 === 0 ){
        arr.push(i);
      }
    }
    return arr;
  }
  return div;
})();

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值