构造函数

  1. 构造函数 本质 其实也是一个函数

    1. 作用 用来创建对象
    2. 以前见过构造函数

    Set 构造函数
    Array 构造函数
    Object
    String
    Number
    Boolean
    Date

    1. 只要它被new 它 就是构造函数

    2. Person 构造函数 首字母是大写(规范)

    3. per 被new出来的对象 !!!

<script>
  
    function Person() {}

     // person 就是一个构造函数 被new
     const per = new Person();

 
   </script>
  • 每一个构造函数中 都存在 有一个 魔鬼 this
    • 构造函数 默认情况下 就是返回了 this

    • this 等于你所new出来的实例 per

    • 只要给构造函数中的this 添加 属性或者方法

    • 那么 实例 自然拥有对应的属性和方法

<script>
     
      function Person() {
        this.username = '悟空'; // per也增加了一个属性
        this.add=()=>{};
        this.clear=()=>{};
      }

      const per = new Person();
      per.username = '悟空';

      const per2 = new Person();

      console.log(per);
      console.log(per2);

    </script>

构造函数-弊端

 <script>
      function Person() {
        this.say = function () {};
      }
      const p1 = new Person();
      const p2 = new Person();
      console.log(p1 === p2); // 两个对象的比较 内存地址 false
      console.log(p1.say === p2.say);// false 两个函数 存放在不同地址中

      // const s1 = new Set();
      // const s2 = new Set();
      // console.log(s1 === s2);// false
      // console.log(s1.add === s2.add); // true 

      // s1 和 s2 共享一个方法   
      // p1 和 p2 没有共享一个 


    </script>

对象在堆中情况

1.值类型 是存在 栈空间 适合存放 固定大小的数据
2. 引用类型(对象、数组、函数) 存在 堆空间 适合存放大小不固定的数据
3. new了两个对象的时候, 两个对象的内存地址 不相等
4. 我们希望 两个对象的方法 内存地址是相等!!!
5. 在构造函数中 当我们定义方法的时候 一般都不会只在在 构造函数中写死
让我们方法 都指向外部 单独声明的方法 多个实例去共享方法!!!

 <script>
      const obj1 = { username: '八戒' };
      const obj2 = { username: '八戒' };

      // console.log(obj1===obj2);// false 内存中的地址

      const obj3 = obj2;
      // console.log(obj3 === obj2); //  true

      obj3.username="悟空";
      console.log(obj2);
    </script>
 <script>
      function say() {
        console.log('外部单独的say方法');
      }
      function Person() {
        this.say = say;
      }

      const p1 = new Person();
      const p2 = new Person();
      console.log(p1 === p2); // false 
      console.log(p1.say === p2.say);// true


      
      const obj1={username:"悟空"};
      const obj2={username:"悟空"};
      const obj3=obj2;
      obj3.username="八戒";
      console.log(obj2);

    </script>

构造函数的基本使用

  1. 构造函数的时候 属性 分成了两种 
    1. 函数类型的属性 
      一般都是写在外部!!!
    2. 非函数类型的属性 
      一般是写在内部!!! 
 <script>
      // 构造函数的方式 创建一个对象

      // 姓名 属性
      // 说出自己的姓名 方法

      function say() {
        console.log('这个是Person的一个方法', this.name);
      }
      function fly() {
        console.log(this.name, '要起飞');
      }

      function Person(name, height) {
        this.name = name;
        this.height = height;
        this.say = say;
        this.fly = fly;
      }
      const p1 = new Person('八戒', 150);
      // p1.say();
      p1.fly();
    </script>

构造函数使用演示

  <script>
      /* 
      1 有一个构造函数  Person
      2 有数字类型的属性 发量 hair =100
      3 有行为  decrease 减少   方法 
        发量 - 1 

      4 按钮 每点击一次 发量减少一根
       */

      function decrease() {
        this.hair--;
      }

      function Person() {
        this.hair = 100;
        this.decrease = decrease;
      }

      const btn = document.querySelector('button');

      const p1 = new Person();
      btn.addEventListener('click', function () {
        // 每点击一次按钮 new一个对象
        p1.decrease();
        console.log(p1.hair);
      });
    </script>

构造函数+原型

  1. 原型 本质是一个对象 在我们创建构造函数的时候就拥有
    2.在原型上添加的一些方法,可以直接被 实例所使用和共享

    1. 可以这么理解 构造函数=父亲 实例=孩子 原型=DNA
    2. 使用面向对象的方式来创建对象
    • 构造函数内部 来定义 非函数类型的属性 如 姓名 身高 肤色 性别
    • 原型来定义 函数类型的属性 函数
 <script>
      // 构造函数 + 原型 搭配来使用
      // 原型 本质 是一个对象
      // 当我们在创建一个 构造函数的时候 原型 被创建
      // 如果我们在原型对象上 增加一个属性或者方法  那么实例 拥有所增加的方法
      // 原型 就是 DNA 构造函数 父亲 实例 孩子

      // function Person() {
      //   this.b = function () {};
      // }

      // // 访问原型
      // // console.log(Person.prototype);
      // Person.prototype.a = function () {
      //   console.log('这个是a方法');
      // };

      // const p1 = new Person();

      // // console.log(p1);
      // p1.a();

      // function Obj() {

      // }
      // Obj.prototype.a=function(){

      // }

      function Person() {
        this.hair = 100;
        // this.decrease = decrease;
      }
      Person.prototype.decrease = function () {
        this.hair--;
      };
    </script>

案例 - 普通写法

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
    />
    <title>17-课堂案例.html</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      img {
        transition: 2s;
      }
      .scale {
        transform: scale(2);
      }
    </style>
  </head>
  <body>
    <button>放大</button>
    <img src="./images/1.png" alt="" />
    <script>
      /* 
      1 静态结构 
      2 给按钮绑定点击事件 
      3 事件触发 
        1 获取图片的dom元素
        2 添加一个class 


      4 面向过程写法 
         
       */

      const button = document.querySelector('button');
      const img = document.querySelector('img');

      button.addEventListener('click', function () {
        img.classList.add('scale');
      });
    </script>
  </body>
</html>

面向对象写法

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
    />
    <title>index.html</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
    </style>
  </head>
  <body>
    <button> 大</button>
    <script>


      function MyImg(src) {
        // body标签上能出现一张图片
        const img = document.createElement('img');
        img.style.transition = '2s';
        // 设置 图片地址
        img.src = src;
        // 在body标签上看见这一张图片
        document.body.append(img);

        this.abc = img;
      }

      // 原型上写一写函数
      MyImg.prototype.scale = function (num) {
        // 获取到 构造函数中 创建的  img dom元素 - 提前把img dom  添加到 this的属性中
        this.abc.style.transform = `scale(${num})`;
      };
      const myImg = new MyImg('./images/1.png'); // body标签上能出现一张图片
      const myImg2=new MyImg("./images/1.png");
      const button = document.querySelector('button');


      button.addEventListener('click', function () {
        // myImg.scale(2);// 
        myImg.scale(3); //  3 倍

        myImg2.scale(5);
      });



    
    </script>
  </body>
</html>

<body>

    <div class="view"></div>
    <button> 大</button>
    <script>


        function MyImg(src) {
            const img = document.createElement(`img`)
            img.style.transition = '2s'
            img.src = src
            this.abc = img
        }
        MyImg.prototype.appendTo = function (e) {
            document.querySelector(e).append(this.abc)
        }
        MyImg.prototype.scale = function (num) {
            this.abc.style.transform = `scale(${num})`
        }
        const myImg = new MyImg('./images/1.png')
        myImg.appendTo(`.view`)
        const button = document.querySelector('button')
        button.addEventListener('click', function () {
            myImg.scale(3)
        })




    </script>
</body>

再次了解原型

  • 万物都是对象
    1. 指的是 obj 数据类型
    2. 指的是 物体
    <script>
      // dom     文档对象模型 
      const div = document.querySelector('div');
      const button = document.querySelector('button');
      // console.log(div);// 把div的标签形式  显示出来  不方便我去了解 div 对象
      console.dir(div);// 把标签 dom元素 以对象的形式显示出来 
      console.dir(button);
    </script>

原型继承-方法

<script>
      /* 
      1 定义一个 父亲  构造函数   有一个方法 say()  Person
      2 定义两个儿子 构造函数 拥有 爸爸的say方法 
        1 YellowPerson
        2 WhitePerson 
       */

      function Person() {}

      Person.prototype.say = function () {
        console.log('这个是父亲定义的say方法');
      };

      function YellowPerson() {}

      //  让儿子去复用父亲的方法
      YellowPerson.prototype.say = Person.prototype.say;
      // 单独和以前一样添加
      YellowPerson.prototype.jump = function () {
        console.log('这个黄种人 儿子 自己的方法');
      };

      function WhitePerson() {}
      WhitePerson.prototype.say = Person.prototype.say;

      const yp = new YellowPerson();
      yp.say();
      yp.jump();

      // const wp=new WhitePerson();
      // wp.say();

      // 普通的html标签  div  img标签
      // div没有src属性 但是id 和 className 属性
      // img 有 src属性,但是id 和className
    </script>

原型继承-属性

 <script>
      // 父亲 构造函数 名称 颜色 身高 体重   属性
      function Person(name, color, height, weight) {
        this.name = name;
        this.color = color;
        this.height = height;
        this.weight = weight;
      }

      // 儿子   名称 颜色 身高 体重  而且 自己  属性  昵称 、 性别
      function YellowPerson(name, color, height, weight, nickname, gender) {
        // 父亲中也有
        Person.call(this,name, color, height, weight);// 属性的继承 ?? 
 
        // 儿子
        this.nickname = nickname;
        this.gender = gender;
      }

      const yp = new YellowPerson('悟空', '黄色', 150, 250, '弼马温', '公');
      console.log(yp);
    </script>

对象中的this

  <script>
      // this 范围很广  主要在 对象中来学习
      // this 对象本身  我自己

      // this 指向 对象本身  可以被修改  通过 call 方法来修改 

      // call 帮助我们调用方法 还可以帮助修改 this 
      // call 在调用方法的时候  还可以传递参数

      const obj = {
        username: '悟空',
        say(a) {
          console.log(this,a);
        },
      };  

      const newObj={
        username:"八戒"
      }
  
      obj.say.call(newObj,123);

    </script>
 ###对象添加属性
<script>
      // 在对象  this = 对象本身的!!    this =  我自己

      // 普通的对象
      const obj = {
        add() {
          // 给对象添加属性  两段代码 封装到一个普通的函数中
          obj.a = 1;
          obj.b = 2;

          // ==== 修改this
          this.c = 3;
          this.d = 4;
        },
      };
      obj.add(); // 让方法帮我们添加属性
      console.log(obj);
    </script>

通过call来动态添加对象

 <script>
      // 普通的函数
      function Person(name, color, height, weight) {
        this.name = name;
        this.color = color;
        this.height = height;
        this.weight = weight;
        // =====
        // obj.name = name;
        // obj.color = color;
        // obj.height = height;
        // obj.weight = weight;
      }

      // 定义一个空的对象
      const obj={};

      Person.call(obj,"悟空","黄色",150,250); // obj 借用了Person方法 来给自己的属性赋值!! 
      // 1 调用了 Person 方法
      // 2 方法内部 给 this赋值   this 等于谁???  obj
      // 3 this.name=悟空; =>  obj.name = 悟空;  //  赋值动作 
      // 3 this.color=黄色; =>  obj.color = 黄色;  //  赋值动作 
      // 3 this.height=150; =>  obj.height = 150;  //  赋值动作 
      // 3 this.weight=250; =>  obj.weight = 250;  //  赋值动作 

      console.log(obj); // 拥有了 Person 函数种 所写的一些属性 


    </script>

构造函数-实例

<script>
      // 我自己 构造函数中的this 指向 实例!!!!!

      // function Person(name, color, height, weight) {
      //   this.name = name;
      //   this.color = color;
      //   this.height = height;
      //   this.weight = weight;
      // }

      // function YellowPerson(name, color, height, weight) {
      //   // 借助了父亲里面的代码  快速帮我们 儿子 的属性赋值
      //   Person.call(this, name, color, height, weight);

      //   // 1 Person.call   函数 Person(普通的函数即可)被调用
      //   // 2 Person 函数的作用 给this赋值
      //   // 3 Person.call(this)  call的作用 修改this的指向
      //       // Person.call(this) this 我自己 =  儿子的构造函数的实例 =  yp
      // }

      // const yp = new YellowPerson('悟空', '黄色', 150, 250);
      // console.log(yp);

      // 属性的继承   子构造函数 借用了父构造函数的  给 实例赋值代码!!
      function Person(name) {
        this.username = name;
      }

      function YellowPerson(name) {
        Person.call(this, name); // 属性的继承
      }

      const yp = new YellowPerson('悟空');
      console.log(yp);
    </script>

构造函数中属性和方法的继承

 <script>
      /* 
      实例 实现 属性和方法的继承
      1 属性的继承 在 儿子的构造函数中 调用 父亲的构造函数 
        父亲的构造函数.call(this,参数。。。)
      2 方法的继承 在儿子的构造函数的原型上 等于 父亲的构造函数的原型 
         儿子的构造函数.prototype.方法名称 =  父亲的构造函数.prototype.方法名称
       */

      function Person(name) {
        this.name = name;
      }

      Person.prototype.say = function () {
        console.log('父亲的say方法');
      };

      function YellowPerson(name, color) {
        Person.call(this, name); // 属性的继承
        this.color = color;
      }

      YellowPerson.prototype.say = Person.prototype.say;
      YellowPerson.prototype.fly = function () {
        console.log('儿子自己的方法 fly');
      };
    </script>

封装+继承案例需求

<script>
      /* 
      案例 : 目的 利用 面向对象的语法和思想 来结合 dom操作 解决实际的问题 

      1 定义父构造函数  
        HTMLElement  
         1 属性  dom 
         2 方法  appendTo 

      2 定义 一个儿子  HTMLDivElement
        1 会继承 父亲 属性和方法 
        2 儿子还有自己独立的功能  
            const  myDiv = new  HTMLDivElement("div中的文本")
            myDiv.appenTo("p")  ;  p标签中会多出有一个 文本为  “div中的文本”  的div
           儿子还会有自己的一个方法
           点击按钮  myDiv.scale(2);   缓慢放大两倍

      3 定义 另外一个儿子  HTMLImgElement 
        1 会继承 父亲 属性和方法  
        2 自己独立的功能
          const myImg = new HTMLImgElement(图片的地址)
          myImg.appendTo("a")  a标签中会多了一个 图片标签
          儿子还会有自己的一个方法
          点击某个按钮  myImg.borderRadius("50%")  缓慢变成 边框圆角 50% 效果 

      4 代码提示 
        1 先根据需求 把 代码的解构整理好   

        2 再去思考实现的逻辑 
       */


       function HTMLElement() {
        //  this.dom=....
       }
       HTMLElement.prototype.appentTo=function(){

       }
    </script>

封装和继承的案例实现

 <button>div放大两倍</button>
    <div class="box"></div>
  <script>
      /* 
        HTMLElement  
         1 属性  dom 
         2 方法  appendTo 
       */

      function HTMLElement() {
        this.dom = document.createElement('div');
      }

      HTMLElement.prototype.appendTo = function (selector) {
        document.querySelector(selector).append(this.dom);
      };

      // 儿子
      function HTMLDivElement(text) {
        HTMLElement.call(this); // this上多一个属性 dom dom = 动态创建的 div元素

        // this.dom =  真实的div 的dom元素
        this.dom.innerText = text;
        this.dom.style.textAlign = 'center';
      }

      // 继承父亲的方法
      HTMLDivElement.prototype.appendTo = HTMLElement.prototype.appendTo;
      // 自己的方法
      HTMLDivElement.prototype.scale = function (num) {
        this.dom.style.transition = '2s';
        this.dom.style.transform = `scale(${num})`;
      };

      const divEle = new HTMLDivElement('div中的文字');
      // console.log(divEle);
      divEle.appendTo('.box');

      const button = document.querySelector('button');
      button.addEventListener('click', function () {
        divEle.scale(2);
      });
    </script>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
    />
    <title>13-实现-封装和继承案例.html</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
    </style>
  </head>
  <body>
    <button>div放大两倍</button>
    <input type="button" value="设置图片缓慢边框圆角效果" />
    <div class="box"></div>
    <script>
      function HTMLElement(tagName) {
        this.dom = document.createElement(tagName);
      }
      HTMLElement.prototype.appendTo = function (select) {
        document.querySelector(select).append(this.dom);
      };

      function HTMLDivElement(text) {
        HTMLElement.call(this, 'div');
        this.dom.innerText = text;
        this.dom.style.textAlign   = 'center';
      }

      HTMLDivElement.prototype.appendTo = HTMLElement.prototype.appendTo;
      HTMLDivElement.prototype.scale = function (num) {
        this.dom.style.transition = '2s';
        
        this.dom.style.transform = `scale(${num})`;
      };

      function HTMLImgElement(src) {
        HTMLElement.call(this, 'img');
        this.dom.src = src;
      }
      HTMLImgElement.prototype.appendTo = HTMLElement.prototype.appendTo;
      HTMLImgElement.prototype.borderRadius = function (num) {
        this.dom.style.transition = '2s';
        this.dom.style.borderRadius = num;
      };

      const divEle = new HTMLDivElement('div中的文字');
      const imgEle = new HTMLImgElement('./images/1.png');

      divEle.appendTo('.box');
      imgEle.appendTo('.box');

      const input = document.querySelector('input');
      const button = document.querySelector('button');
      input.addEventListener('click', function () {
        imgEle.borderRadius('50%');
      });
      button.addEventListener('click', function () {
        divEle.scale(2)
      });
    </script>
  </body>
</html>

类的基本使用

<script>
      /* 
      1 构造函数 来创建对象 
      2 对象 两种信息
        1 属性
        2 方法 
       */


      //  es6 新 简洁  class 面向对象

      class Person {
        name = '悟空';
        color = '黄色';
        say() {
          console.log(this.name, this.color);
        }
        fly(){
          console.log(this.name,"起飞");
        }
      }

      // es5 原型链方式实现  面向对象
      // function Person() {
      //   this.name="悟空";
      //   this.color="黄色";
      // }
      // Person.prototype.say=function(){
      //   console.log(this.name,this.color);
      // }

      const p1 = new Person();
      p1.say();
      p1.fly();
    </script>
<script>
      /* 
      1 使用 class来定义属性的时候
        1 如果 这个属性 你写死 
          class Person {
            name="悟空";
            color="黄色";
          }
        2 如果 属性 可以由外部传入 必须使用构造器
          constructor(name,color){
            this.name=name;
            this.color=color;
          }
      
      
      
      
      
       */
      class Person {
        // 构造器
        constructor(name, color) {
          // 当 Person被new的时候 这个构造器 就会被调用

          console.log('person被new啦');
          // console.log(name,color);

          // this 还是指向 实例
          this.name = name;
          this.color = color;
        }
        say() {
          console.log(this.name, this.color);
        }
      }

      const p1 = new Person('悟空', '黄色');
      console.log(p1);
    </script>

类的方式来实现继承

 <script>
      /* 
      父构造函数 Person 
      1 属性 name = "父亲"
      2 方法 say 说话

      儿子 去继承 父亲
      1 属性 
      2 方法
       */

      //  function Person() {
      //    this.name="父亲";
      //  }
      //  Person.prototype.say=function(){
      //    console.log(this.name,"父亲的say方法");
      //  }

      //  function YellowPerson() {
      //    Person.call(this);
      //  }

      //  YellowPerson.prototype.say=Person.prototype.say;

      // es6 类去实现继承
      class Person {
        name = '父亲';
        say() {
          console.log(this.name, '父亲的say方法');
        }
      }

      // 直接就实现了 继承父亲的属性和方法 !!!!
      class YellowPerson extends Person {}
      // 儿子实例 拥有 父亲 name属性和父亲的 say方法
      const yp = new YellowPerson();
      console.log(yp);
    </script>
<script>
      /* 
      对于子类来说 
      1 如果你写了  extends 而且 还写 constructor 
        那么在我们的 constructor 必须要调用super 固定语法!! 

      2 为什么 之前只写  extends 不用写super-没有写 constructor

      
      
       */
      class Person {
        constructor(name, color) {
          this.name = name;
          this.color = color;
        }
      }

      class YellowPerson extends Person {
        // 默认的代码
        constructor(name, color, height, weight) {
          super(name, color);// 调用父亲的构造器 给儿子 添加属性 
          this.height = height;
          this.weight = weight;
        }
      }

      const yp = new YellowPerson('悟空', '黄色', 100, 200);
      console.log(yp);
    </script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容