ES5构造函数和ES6基础

ES5构造函数

  • 面向对象是一种思想 —考虑的是怎么去调用它,不需要关注内部的实现
  • 面向过程也是一种思想

面向对象分为两个层次:

  • 使用对象 – 属性和方法

    • Array
      push()
    • String
    • Math
    • Number
    • Date
    • Reg
    • Window
    • Document
    • location
  • 构造对象 --系统对象没有提供的方法,需要自己构造

    • 对象的构成:属性和方法
  • 面向对象的三大特性:

    • 抽象: 抽:抽离出核心的属性构造对象
    • 封装: 封装:封装一个具体特定功能的代码模块—复用强
    • 继承: 继承:就是继承父亲的优秀基因(方法等),然后直接在提升自己的能力(也就是你的就是我的,我的还是我的)
    • 多态: 组件化开发(并列关系)

    eg:就是一个办公系统
    姓名 性别 年龄 地址 工号 等等 这些可以可以抽离到一个对象身上,再进行

    eg:多态是什么?
    就是有着公共的代码,但是也是有着独一无二的功能,比如选项卡

    • 功能1: 普通版本
    • 功能2:拖拽
    • 功能3:可以增加栏目

使用对象

  • 变量与属性,函数与方法的区别
    属性的本质是变量,只不过这个变量是挂载在一个对象身上,我们为了区分它们,也就称之为对象的属性
    方法的本质是函数,只不过这个函数是挂载在一个对象身上,我们为了区分它们,也就称之为对象的方法
    let num = 90; //变量
    let arr = [1, 3, 5] //数组
    arr.num1 = 20; //属性:num1本质是一个变量,但是挂载在arr对象身上,也就称之为属性

    function a() { //函数
      console.log(a);

    }
    a()
    arr.bb = function () { //方法:本质上是一个函数,但是挂载在arr对象身上,我们称之为方法
      console.log(bb);
    }
    arr.bb()
    arr.push(); //调用方法

注意点:自己构造一个对象的方法的时候,不要挂载在原本对象身上,避免方法的重名,这需要使用一个空对象,来挂载
也就是 let obj = new Object();

构造对象

  • 工厂模式构造函数
  • 构造函数结合原型对象实现方法的共享!
    注意点:原型对象之内定义的是公共的属性和方法!

new 的作用:

  • 1:构造函数都有着自己的原型对象
  • 2:构造函数的原型对象有一个属性:constructor属性,它指回自己的构造函数
  • 3:new 一个实例,也就是创建一个实例对象,可以同时创建多个不同的实例对象
  • 4:实例对象和原型之间存在一条连接,也就是原型链

原型用法: 构造函数(对象).原型.方法名 = function(){}

  • 每一个构造函数下都有一个原型
  • 每一个对象和自己的原型都有着一条连接,这个链接就是原型链!

注意点:

  • 每一个对象(构造函数实例化的对象)都会从原型对象中“继承”属性
  • proto :这是每个对象(除null外)都会有的属性,叫做__proto__,这个属性会指向该对象的原型

构造函数结合原型对象实现方法的共享

    /*
      需求:
        需要创建两个对象,小黑,小白,年龄分别为20,30,居住地为傻屌之村,
        小黑喜欢吃辣,小白喜欢吃素,小黑是乡村歌手,小白是歌王

        按照上面要求:
        + 01:需要定义一个构造函数,里面还定义者name和age(不同的姓名和年龄,定义在构造函数内)
        + 02:而居住地方是同一个地方,也就是公共的属性,那么需要定义在原型对象内
        + 03:而小黑和小白都有着公共的eat和song方法
    */
    function Peasonl(stuName, stuAge) {
      this.name = stuName;
      this.age = stuAge;
    }
    Peasonl.prototype.adr = "傻屌之村"
    Peasonl.prototype.eat = function (food) {
      console.log(this.name + food);
    }
    Peasonl.prototype.song = function (song) {
      console.log(this.name + song);
    }

    let xiaohei = new Peasonl("小黑", 20);
    let xiaobai = new Peasonl("小白", 30);
    console.log(xiaohei); //Peasonl {name: "小黑", age: 20}
    xiaohei.eat("喜欢吃辣"); //小黑喜欢吃辣
    xiaohei.song("-乡村歌手") //小黑-乡村歌手
    console.log(xiaohei.name + xiaohei.adr); //小白-傻屌之村

    xiaobai.eat("喜欢吃素") //小白喜欢吃素
    xiaobai.song("-歌王"); //小白-歌王
    console.log(xiaobai.name + xiaobai.adr);
    /*
      构造函数:属性和方法
       * 属性:定义在构造函数之内
       * 方法:定义在原型对象之内 --- 这样可以实现,每一实例对象都共享这个方法!
    */

原型链

原型链的查找机制:

  • 1:读取实例对象,在实例对象身上查找是否含有该属性,若是有就是直接使用,否者到2
  • 2:没有找到的话,就去实例对象的原型对象中查找,有就返回这个属性的值,否则到3
  • 3:没有找到haul,就到原型对象中的原型对象查找,若是没有,直接查找到Object这个对象(顶级对象)
  • 4:若是Object对象还是没有查找到这个属性,就返回undefined

在这里插入图片描述

prototype和__proto__的区别:

prototype:原型对象

  • 每一个构造函数都有着一个原型对象
  • 原型对象内有着一个属性:constructor —它指回构造函数

proto:对象的原型

  • 每一个实例对象都有着一个对象的原型
  • 这个对象的原型指向原型对象
    function Person(name, age) {
      this.name = name; //在构造函数中定义的属性---私有的属性
      this.age = age;
    }
    Person.prototype.adr = "小山村"; //在原型对象上定义的属性---共享属性
    Person.prototype.say = function (say0) { //在原型对象上定义的方法---共享方法
      console.log(this.name + say0);
    }
    let p1 = new Person("小黑");
    let p2 = new Person("小白");
    console.log(Person.prototype === p1.__proto__);
//true 证明两者都指向同一个原型对象,也就是说他们是等价的

class

  • 概念:class 关键字表明类的声明;
  • 作用 :非常明确 : 面向对象编程的工具;
  • 组成:定义一个类,类里面是由构造函数 和 原型方法!
    • 构造函数:一般用于存储数据
    • 原型方法:用于存储功能的!
 class Factory {
    // 构造函数变成了统一的名称 : constructor
    constructor() {
      this.a = "这是一条数据";
    }
    // 定义任意名称的构造函数方法名;
    init() {
      console.log("这是一个功能")
    }
  }
  // 调用 : 
  // class 的调用 和 构造函数 + 原型的调用是一致的;
  var fac = new Factory()
  fac.init();

需求:实现一个简单的拖拽功能

  • 01:文档(也就是光标)按下的时候,获取到初始值的位置,
  • 02: 文档移动的时候,盒子粘连在鼠标之上,跟着移动,也就是需要 把当前的值 => 赋值为盒子 (可视区 - 最初),使得盒子向鼠标光标居中(左上走)
  • 03:文档抬起的时候,就取消拖拽效果!
    class Drag {
      constructor(selector) {
        this.ele = document.querySelector(selector)
        this.bindEvent();
      }
      bindEvent() {
        let self = this;
        //01:鼠标按下的时候,获取到当前的位置,赋值为盒子,使得盒子向鼠标光标居中(左上走)
        document.onmousedown = function (evt) {
          let e = evt || event;
          let {
            offsetX: x,
            offsetY: y
          } = e;
          //02: 鼠标移动的时候,盒子粘连在鼠标之上,跟着移动,也就是需要 把当前的值 => 赋值为盒子 (可视区 - 最初),使得盒子向鼠标光标居中(左上走)
          document.onmousemove = function (evt) {
            let e = evt || event;
            self.eleMove(e.clientX - x, e.clientY - y);
          }
        }
        //03:鼠标抬起的时候,就取消拖拽效果!
        document.onmouseup = function () {
          document.onmousemove = null;
        }
      }
      eleMove(x, y) {
        this.ele.style.left = x + "px";
        this.ele.style.top = y + "px";
      }
    }
    new Drag("#box");

实现一个可继承父类

    //需求:
    // * 01:文档(也就是光标)按下的时候,获取到初始值的位置,
    // * 02: 文档移动的时候,盒子粘连在鼠标之上,跟着移动,也就是需要 把当前的值 => 赋值为盒子 (可视区 - 最初),使得盒子向鼠标光标居中(左上走)
    // * 03:文档抬起的时候,就取消拖拽效果!
    // * 04:实现一个继承的拖拽效果,就是边界判断! 在子类之中,覆盖父类的元素移动方法
    // * 05:继承的话,调用的时候是调用子类的!
    class Drag {
      constructor(selector) {
        this.ele = document.querySelector(selector);
        this.bindEvent()
      }
      bindEvent() {
        let self = this;
        // 01:文档(也就是光标)按下的时候,获取到初始值的位置,
        document.onmousedown = function (evt) {
          let e = evt || event;
          let {
            offsetX: x,
            offsetY: y
          } = e;
          // 02: 文档移动的时候, 盒子粘连在鼠标之上, 跟着移动, 也就是需要 把当前的值 => 赋值为盒子(可视区 - 最初), 使得盒子向鼠标光标居中( 左上走) document.onmousemove =
          document.onmousemove = function (evt) {
            let e = evt || event;
            //调用移动元素函数
            self.eleMove(e.clientX - x, e.clientY - y);
          }
        }
        // 03:文档抬起的时候,就取消拖拽效果!
        document.onmouseup = function () {
          document.onmousemove = null;
        }
      }
      //元素移动
      eleMove(x, y) {
        this.ele.style.left = x + "px";
        this.ele.style.top = y + "px";
      }
    }

    //继承父元素中带有边界的!
    class boundaryDrag extends Drag {
      constructor(selector) {
        console.log("带有边界");
        super(selector)
      }
      eleMove(x, y) {
        //最下值判断
        x = x < 0 ? 0 : x;
        y = y < 0 ? 0 : y;
        //最大值的判断
        this.ele.style.left = x + "px";
        this.ele.style.top = y + "px";
      }
    }
    let drg1 = new boundaryDrag("#box");

ES5的继承

  • 概念:
    • 01:构造函数中的属性拿出来
    • 02:原型对象上的方法拿出来
    • 03:继承构造数里面功能和调用;
ES5之中普通的继承
    function Father() {
      this.a = "你好";
      this.b = "世界";
    }
    new Father()

    function Son() {
      var son_this = this;
      Father.call(son_this)
    }
    var son = new Son();
    console.log(son); //Son {a: "你好", b: "世界"}
    //通过call的方法,在son里面调用父函数,然后把里面的this转接到son之上,于是也就继承了Father的属性
带有参数的继承
    //一个son自带参数的继承
    function Father(a, b) {
      this.a = a
      this.b = b;
    }
    new Father()

    function Son(son_a, son_b) {
      var son_this = this;
      Father.call(son_this, son_a, son_b)
    }
    var son = new Son("我是", "你是")
    console.log(son); //Son {a: "我是", b: "你是"}
原型方法的继承
    //原型方法的继承
    function Father() {}
    Father.prototype.init = function () {
      console.log("我是father上原型方法");
    }
    new Father();

    function Son() {}

    //遍历父构造函数的原型,然后把原型对象身上的方法,赋值给子函数!
    for (var key in Father.prototype) {
      console.log(Father.prototype[key]);
      Son.prototype[key] = Father.prototype[key]
    }

    var son = new Son();
    son.init() //我是father上原型方法

需求:既需要传递参数,也需要继承父构造函数的方法!

    function Drag(selector) {
      this.ele = document.querySelector(selector);
      this.bindEvent()
    }
    Drag.prototype.bindEvent = function () {
      let self = this;
      // 01:文档(也就是光标)按下的时候,获取到初始值的位置,
      document.onmousedown = function (evt) {
        let e = evt || event;
        let {
          offsetX: x,
          offsetY: y
        } = e;
        // 02: 文档移动的时候, 盒子粘连在鼠标之上, 跟着移动, 也就是需要 把当前的值 => 赋值为盒子(可视区 - 最初), 使得盒子向鼠标光标居中( 左上走) document.onmousemove =
        document.onmousemove = function (evt) {
          let e = evt || event;
          //调用移动元素函数
          self.eleMove(e.clientX - x, e.clientY - y);
        }
      }
      // 03:文档抬起的时候,就取消拖拽效果!
      document.onmouseup = function () {
        document.onmousemove = null;
      }
    }
    //元素移动
    Drag.prototype.eleMove = function (x, y) {
      this.ele.style.left = x + "px";
      this.ele.style.top = y + "px";
    }

    function boundaryDrag(selector) {
      var son_this = this;
      Drag.call(son_this, selector)
    }

    //继承父元素中带有边界的!
    for (var key in Drag.prototype) {
      boundaryDrag.prototype[key] = Drag.prototype[key];
    }


    boundaryDrag.prototype.eleMove = function (x, y) {
      //最下值判断
      x = x < 0 ? 0 : x;
      y = y < 0 ? 0 : y;
      this.ele.style.left = x + "px";
      this.ele.style.top = y + "px";
    }
    let drg1 = new boundaryDrag("#box");

原型链的继承

  • 原理:就是把父元素的实例对象(指向的是父构造函数的原型对象) 赋值给Son的原型对象,这样的话,Son原型对象指向的是 父构造函数的原型对象 而原型对象存储这方法! 可用于继承!
    function Father() {}
    Father.prototype.init = function () {
      console.log("我是父的初始化");
    }
    Father.prototype.show = function () {
      console.log("我是父的显示");
    }

    function Son() {}
    //把父元素的实例对象(指向的是父构造函数的原型对象) 赋值给Son的原型对象 这样的话 Son原型对象指向的是 父构造函数中的原型对象!
    Son.prototype = new Father()
    // console.log(Son); //Father{}

    Son.prototype.show = function () {
      console.log("我是子的显示");
    }
    var son = new Son();
    son.init() //我是父的初始化
    son.show() // 我是子的显示
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值