JS进阶 3——深入面向对象、原型

news/2024/10/3 13:58:54 标签: javascript, 前端, 开发语言

JS 进阶3——深入面向对象、原型

1.编程思想

  • 面向过程:分析出解决问题的过程,然后用函数将这些步骤一步步封装起来
  • 面向对象:将事物分为一个个对象,然后对象之间分工合作

2.构造函数:封装性、面向对象

  • 构造函数方法存在浪费内存的问题(构造函数中的方法每次调用)

      function Star(name, age) {
          this.name = name
          this.age = age
          this.sing = function () {
            console.log('我会唱歌')
          }
        }
        const xxg = new Star('小小怪', 18)
        const ddg = new Star('大大怪', 22)
        console.log(xxg.sing === ddg.sing) //返回false,重复创建两个sing
    

3.原型——解决构造函数浪费内存的问题

  • 什么是原型

    • 构造函数通过原型分配的函数是所有对象所共享的
    • JS中,每个构造函数都有一个prototype属性,指向另一个对象,称为原型对象
    • 原型对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
    • 可以把不变的方法直接定义到prototype对象上,这样所有对象的实例可以共享这些方法
    • 构造函数和原型对象中的this都指向实例化的对象
    //1.公共属性写到构造函数中
        function Star(name, age) {
          this.name = name
          this.age = age
        }
    //2.公共方法写到原型对象身上
        Star.prototype.sing = function () {
          console.log('唱歌');
    
        }
        const xxg = new Star('小小怪', 18)
        const ddg = new Star('大大怪', 22)
        xxg.sing()
        ddg.sing()
        console.log(xxg.sing === ddg.sing) //返回true
    

    eg:为数组对象添加方法(注意想要不传参,就要使用this指向实例对象)

     //为数组拓展 求最大值方法
        Array.prototype.max = function () {
          return Math.max(...this)
        }
        //为数组拓展 求和方法
        Array.prototype.sum = function () {
          return this.reduce((prev, current) => prev + current)
        }
        const str = [1, 2, 3]
        console.log(str.max())
        console.log(str.sum())
    
  • constructor(构造函数)属性

    • 每个原型对象中都有一个constructor属性
    • 该属性指向该原型对象的构造函数,标明该原型对象属于哪个构造函数
    //创建一个构造函数
        function Star() {
        }
        //想要为该构造函数一次性挂载多个方法
        Star.prototype = {
          //重新指回创造这个原型对象的构造函数
          constructor: Star,
          sing: function () {
            console.log('我喜欢唱歌');
          },
          dance: function () {
            console.log('我喜欢跳舞');
          }
        }
        console.log(Star.prototype) //返回undefined
        //意味着找不到该原型对象的构造函数了
        //解决办法:在原型对象中重新指回创造这个原型对象的构造函数
    
  • 对象原型

    • 对象都会有一个 __ proto__ 指向构造函数的prototype原型对象,之所以对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象 __ proto __ 的存在
    • 只能获取不能赋值
    • 对象原型是实例对象的属性,指向原型对象,有一个属性constructor指向构造函数;原型对象是构造函数的属性,是一个对象,也有一个属性constructor指向构造函数
     function Star() { }
        const ldh = new Star()
        console.log(ldh.__proto__ === Star.prototype)
        //返回true
    
  • 原型继承

    • 借助原型对象实现继承的特性
        //人 父构造函数
        function People() {
          this.eyes = 2
          this.head = 1
        }
        //女人  构造函数 继承People
        function Woman() {
    
        }
    	//子类的原型 = new 父类,方便给子类添加特殊的属性和方法
        Woman.prototype = new People()
        //指回构造函数
        Woman.prototype.constructor = Woman
        //给女人添加方法
        Woman.prototype.baby = function () {
          console.log('宝贝')
    
        }
        const red = new Woman()
        console.log(red)
    
    
        //男人  构造函数 继承People
        function Man() {
    
        }
        Man.prototype = new People()
        Man.prototype.constructor = Man
        const blue = new Man()
        console.log(blue)
    
  • 原型链:就是一个查找规则,先从自身原型对象查找属性和方法,找不到就往上一层查找,原型链就是往上查找的这样一个路线。

在这里插入图片描述

  • instanceof运算符:用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上
  • 案例:使用原型实现模态框封装:
<!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>面向对象封装消息提示</title>
  <style>
    .modal {
      width: 300px;
      min-height: 100px;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
      border-radius: 4px;
      position: fixed;
      z-index: 999;
      left: 50%;
      top: 50%;
      transform: translate3d(-50%, -50%, 0);
      background-color: #fff;
    }

    .modal .header {
      line-height: 40px;
      padding: 0 10px;
      position: relative;
      font-size: 20px;
    }

    .modal .header i {
      font-style: normal;
      color: #999;
      position: absolute;
      right: 15px;
      top: -2px;
      cursor: pointer;
    }

    .modal .body {
      text-align: center;
      padding: 10px;
    }

    .modal .footer {
      display: flex;
      justify-content: flex-end;
      padding: 10px;
    }

    .modal .footer a {
      padding: 3px 8px;
      background: #ccc;
      text-decoration: none;
      color: #fff;
      border-radius: 2px;
      margin-right: 10px;
      font-size: 14px;
    }

    .modal .footer a.submit {
      background-color: #369;
    }
  </style>
</head>

<body>
  <button id="delete">删除</button>
  <button id="login">登录</button>

  <!-- <div class="modal">
    <div class="header">温馨提示 <i>x</i></div>
    <div class="body">您没有删除权限操作</div>
  </div> -->


  <script>javascript">
    //构造函数封装——模态框
    function Modal(title = '', message = '') {
      //创建div标签
      this.modalBox = document.createElement('div')
      //给div标签添加类名为modal
      this.modalBox.className = 'modal'
      //modal盒子内部填充2个div标签并且修改文字内容
      this.modalBox.innerHTML = `
        <div class="header">${title} <i>x</i></div>
    <div class="body">${message}</div>
      `
      console.log(this.modalBox)
    }
    Modal.prototype.open = function () {
      const box = document.querySelector('.modal')
      //防止创建多个模态框,使其有则移除,没有就继续执行
      box && box.remove()
      document.body.append(this.modalBox)
      //x要在模态框创建完成后才能点击关闭
      this.modalBox.querySelector('i').addEventListener('click', () => {
        this.close()
      })
    }
    Modal.prototype.close = function () {
      this.modalBox.remove()
    }
    document.querySelector('#delete').addEventListener('click', () => {
      const del = new Modal('温馨提示', '您没有权限删除操作')
      del.open()
    })
    document.querySelector('#login').addEventListener('click', () => {
      const login = new Modal('友情提示', '您没有注册呢?')
      login.open()
    })
  </script>
</body>

</html>

http://www.niftyadmin.cn/n/5688490.html

相关文章

基于SpringBoot+Vue+MySQL的民宿预订平台

系统展示 用户前台界面 管理员后台界面 商家后台界面 系统背景 随着旅游业的蓬勃发展&#xff0c;民宿作为一种独特的住宿方式&#xff0c;受到了越来越多游客的青睐。然而&#xff0c;传统的民宿预定方式往往存在信息不对称、效率低下等问题&#xff0c;难以满足游客的个性化需…

关于鸿蒙next 调用系统权限麦克风

使用app的时候都清楚&#xff0c;想使用麦克风、摄像头&#xff0c;存储照片等&#xff0c;都需要调用系统的权限&#xff0c;没有手机操作系统权限你也使用不了app所提供的功能&#xff0c;虽然app可以正常打开&#xff0c;但是你需要的功能是没办法使用的。今天把自己在鸿蒙学…

Redis: Sentinel工作原理和故障迁移流程

Sentinel 哨兵几个核心概念 1 ) 定时任务 Sentinel 它是如何工作的&#xff0c;是如何感知到其他的 Sentinel 节点以及 Master/Slave节点的就是通过它的一系列定时任务来做到的&#xff0c;它内部有三个定时任务 第一个就是每一秒每个 Sentinel 对其他 Sentinel 和 Redis 节点…

如何使用 Python 读取数据量庞大的 excel 文件

使用 pandas.read_excel 读取大文件时&#xff0c;的确会遇到性能瓶颈&#xff0c;特别是对于10万行20列这种规模的 .xlsx 文件&#xff0c;常规的 pandas 方法可能会比较慢。 要提高读取速度&#xff0c;关键是找到更高效的方式处理 Excel 文件&#xff0c;特别是在 Python 的…

计算机网络:计算机网络体系结构 —— OSI 模型 与 TCP/IP 模型

文章目录 计算机网络体系结构OSI 参考模型TCP/IP 参考模型分层的必要性物理层的主要问题数据链路层的主要问题网络层的主要问题运输层的主要问题应用层的主要问题 分层思想的处理方法发送请求路由器转发接受请求发送响应接收响应 计算机网络体系结构 计算机网络体系结构是指将…

结合vueuse实现图片懒加载

介绍 为什么要有懒加载&#xff1f; 在一个网页中如果有很多张图片&#xff0c;那么用户初进这个页面的时候不必一次性把所有图片都加载出来&#xff0c;否则容易造成卡顿和浪费。应该是&#xff0c;用户的视图页面滑到该图片的位置&#xff0c;然后再把该图片加载出来。 前置…

rabbitMq-----路由匹配模块

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言交换机类型binding_key 和 routing_key匹配算法 前言 交换机有三种类型&#xff0c;直接交换&#xff0c;广播交换&#xff0c;主题交换。 其中交换机类型不同…

LabVIEW提高开发效率技巧----快速实现原型和测试

在LabVIEW开发中&#xff0c;DAQ助手&#xff08;DAQ Assistant&#xff09;和Express VI为快速构建原型和测试功能提供了极大的便利&#xff0c;特别适合于简单系统的开发和早期验证阶段。 DAQ助手&#xff1a;是一种可视化配置工具&#xff0c;通过图形界面轻松设置和管理数据…