JS进阶-原型

学习目标:

  • 掌握原型

学习内容:

  1. 原型
  2. constructor属性
  3. 对象原型
  4. 原型继承
  5. 原型链
  6. 综合案例

原型:

构造函数通过原型分配的函数是所有对象所共享的

JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也称为原型对象。

这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存。

我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。

构造函数和原型对象中的this都指向 实例化的对象。

在这里插入图片描述

<title>原型</title>
</head>

<body>
  <script>
    // 构造函数  公共的属性和方法 封装到 Star 构造函数里面了
    // 1.公共的属性写到 构造函数里面
    function Star(uname, age) {
      this.uname = uname
      this.age = age
      // this.sing = function () {
      //   console.log('唱歌')
      // }
    }
    // 2. 公共的方法写到原型对象身上   节约了内存
    Star.prototype.sing = function () {
      console.log('唱歌')
    }
    const ldh = new Star('刘德华', 55)
    const zxy = new Star('张学友', 58)
    ldh.sing() //调用
    zxy.sing() //调用
    // console.log(ldh === zxy)  // false
    console.log(ldh.sing === zxy.sing)

    // console.dir(Star.prototype)
  </script>

</body>

在这里插入图片描述

  • 小结
  1. 原型是什么?

一个对象,我们也称为prototype为原型对象

  1. 原型的作用是什么?

共享方法。
可以把那些不变的方法,直接定义在prototype对象上。

  1. 构造函数和原型里面的this指向谁?

实例化的对象。

  • 原型-this指向

构造函数和原型对象中的this指向 实例化的对象。

<title>构造函数和原型的this指向</title>
</head>

<body>
  <script>
    let that
    function Star(uname) {
      // that = this
      // console.log(this)
      this.uname = uname
    }
    // 原型对象里面的函数this指向的还是 实例对象 ldh
    Star.prototype.sing = function () {
      that = this
      console.log('唱歌')
    }
    // 实例对象 ldh   
    // 构造函数里面的 this 就是  实例对象  ldh
    const ldh = new Star('刘德华')
    ldh.sing()
    console.log(that === ldh)  //true
  </script>

</body>
  • 练习
 <title>练习-给数组扩展方法</title>
</head>

<body>
  <script>
    //自己定义 数组扩展方法 求和  和  最大值
    //1.我们定义的这个方法,任何一个数组实例对象都可以使用
    //2.自定义的方法写到 数组.prototype 身上
    //1.最大值
    const arr = [1, 2, 3]
    Array.prototype.max = function () {
      //展开运算符
      return Math.max(...this)
      //原型函数里面的this指向谁?  实例对象  arr
    }

    //2.最小值
    Array.prototype.min = function () {
      //展开运算符
      return Math.min(...this)
      //原型函数里面的this指向谁?  实例对象  arr
    }
    console.log(arr.max())
    console.log([2, 5, 9].max())
    console.log(arr.min())

    // const arr = new Array(1,2)
    // console.log(arr)

    //3.求和方法
    Array.prototype.sum = function () {
      return this.reduce((prev, item) => prev + item, 0)
    }
    console.log([1, 2, 3].sum())
    console.log([11, 21, 31].sum())

  </script>

</body>

constructor属性:

每个原型对象里面都有个constructor属性(constructor 构造函数)。

作用:该属性指向该原型对象的构造函数简单理解,就是指向我的爸爸,我是有爸爸的孩子。
在这里插入图片描述

  • 使用场景

如果有多个对象的方法,我们可以给原型对象采取对象形式赋值。

但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象constructor就不再指向当前构造函数了。

此时,我们可以在修改后的原型对象中,添加一个constructor指向原来的构造函数。

 <title>constructor属性</title>
</head>
<body>
  <script>
      // constructor  单词 构造函数
 
    // Star.prototype.sing = function () {
    //   console.log('唱歌')
    // }
    // Star.prototype.dance = function () {
    //   console.log('跳舞')
    // }
    function Star() {
    }
    // console.log(Star.prototype)
    Star.prototype = {
      // 从新指回创造这个原型对象的 构造函数
      constructor: Star,
      sing: function () {
        console.log('唱歌')
      },
      dance: function () {
        console.log('跳舞')
      },
    }
    console.log(Star.prototype)
    // console.log(Star.prototype.constructor)
 
    // const ldh = new Star()
    // console.log(Star.prototype.constructor === Star) //true
  </script>
  
</body>
  • 小结
  1. constructor 属性的作用是什么?

指向该原型对象的构造函数。


对象原型:

对象都会有一个属性_proto_指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype 。

原型对象的属性和方法,就是因为对象有_proto_原型的存在。
在这里插入图片描述

  • 注意
  1. _proto_是JS非标准属性。
  2. [[_proto_]]_proto_意义相同。
  3. 用来表明当前实例对象指向哪个原型对象prototype。
  4. _proto_对象原型里面也有一个constructor属性,指向创建该实例对象的构造函数。
 <title>对象原型</title>
</head>

<body>
  <script>
    function Star() {

    }
    const ldh = new Star()
    // 对象原型__proto__ 指向 改构造函数的原型对象
    console.log(ldh.__proto__)
    // console.log(ldh.__proto__ === Star.prototype)  //true
    // 对象原型里面有constructor 指向 构造函数 Star
    console.log(ldh.__proto__.constructor === Star)  //true
  </script>

</body>
  • 小结
  1. prototype是什么?哪里来的?

原型(原型对象)。
构造函数都自动有原型。

  1. constructor属性在哪里?作用干啥的?

prototype原型和对象原型_proto_里面都有。
指向创建实例对象/原型的构造函数

  1. _proto_属性在哪里?指向谁?

在实例对象里面。
指向原型prototype

  • 练习
function Star() {

    }
    const ldh = new Star()
    // 对象原型__proto__ 指向 改构造函数的原型对象
    console.log(ldh.__proto__)
    // console.log(ldh.__proto__ === Star.prototype)  //true
    // 对象原型里面有constructor 指向 构造函数 Star
    console.log(ldh.__proto__.constructor === Star)  //true

在这里插入图片描述


原型继承:

继续是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript中大多是借助原型对象实现继承的特性。

<title>原型继承</title>
</head>

<body>
  <script>
    //继续抽取  公共的部分放到原型上
    // const Person = {
    //   eyes: 2,
    //   head: 1
    // }
    //构造函数 new出来的对象  结构一样,但是对象不一样
    function Person() {
      this.eyes = 2
      this.head = 1
    }


    //女人  构造函数  继承  想要继承Person
    function Woman() {
      this.eyes = 2
      this.head = 1
    }
    //Woman 通过原型来继承 Person
    // 父构造函数(父类)   子构造函数(子类)
    // 子类的原型 =  new 父类  
    Woman.prototype = new Person()  // {eyes: 2, head: 1} 
    //指回原来的构造函数
    Woman.prototype.constructor = Woman

    //给女人添加一个方法  来姨妈
    Woman.prototype.yuejing = function () {
      console.log('来姨妈')
    }
    const red = new Woman()
    console.log(red)
    // console.log(Woman.prototype)



    //男人 构造函数  继承  想要继承Person
    function Man() {
      this.eyes = 2
      this.head = 1
    }
    //Man 通过原型来继承 Person
    Man.prototype = new Person()
    //指回原来的构造函数
    Man.prototype.constructor = Man
    const blue = new Man()
    console.log(blue)
    // console.log(Man.prototype)
  </script>

</body>

原型链:

基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链。
在这里插入图片描述

<title>原型链</title>
</head>

<body>
  <script>
    // function Objetc() {}
    console.log(Object.prototype)
    console.log(Object.prototype.__proto__) //null

    function Person() {

    }
    const ldh = new Person()
    // console.log(ldh.__proto__ === Person.prototype) //true
    // console.log(Person.prototype.__proto__ === Object.prototype)  //true
    console.log(ldh instanceof Person) //true
    console.log(ldh instanceof Object) //true
    console.log(ldh instanceof Array)  //false
    console.log([1, 2, 3] instanceof Array) //true
    console.log(Array instanceof Object) //true
  </script>

</body>

在这里插入图片描述

  • 原型链-查找规则
  1. 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
  2. 如果没有就查找它的原型(也就是__proto__指向的prototype原型对象)。
  3. 如果还没有就查找原型对象的原型(Object的原型对象)。
  4. 依次类推一直找到Object为止(null)。
  5. __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线。
  6. 可以使用instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上。

综合案例:

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

<head>
  <meta charset="UTF-8">
  <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>
    //1.Modal 构造函数封装 - 模态框
    function Modal(title = '', message = '') {
      // console.log(title, message)
      //创建 modal模态框盒子
      //1.1创建div标签
      this.modalBox = document.createElement('div')
      //1.2给div标签添加类名为modal
      this.modalBox.className = 'modal'
      //1.3 modal 盒子内部填充2个div标签并且修改文字内容
      this.modalBox.innerHTML = `
      <div class="modal">
      <div class="header">${title} <i>x</i></div>
      <div class="body">${message}</div>
    </div>
      
      `
      console.log(this.modalBox)


    }

    // new Modal('温馨提示', '您没有删除权限操作')
    // new Modal('友情提示', '您还没有登录呢')

    //2.给构造函数原型对象挂载 open 方法
    Modal.prototype.open = function () {
      //先来判断页面中是否有modal盒子,如果有先删除,否则继续添加
      const box = document.querySelector('.modal')
      box && box.remove()
      //注意这个方法不要用箭头函数
      //把刚才创建的modalBox 显示到页面body中
      document.body.append(this.modalBox)

      //要等着盒子显示出来,就可以绑定点击事件了
      this.modalBox.querySelector('i').addEventListener('click', () => {
        //这个地方需要用到箭头函数
        //这个this指向  实例对象
        this.close()
      })
    }

    //3.给构造函数原型对象挂载 close方法
    Modal.prototype.close = function () {
      this.modalBox.remove()
    }




    //测试一下 点击 删除按钮
    document.querySelector('#delete').addEventListener('click', () => {
      //先调用 Modal 构造函数
      const del = new Modal('温馨的提示', '您没有删除权限操作')
      //实例对象调用open方法
      del.open()
    })

    //测试一下 点击 删除按钮
    document.querySelector('#login').addEventListener('click', () => {
      //先调用 Modal 构造函数
      const login = new Modal('友情的提示', '您还没有登录呢')
      //实例对象调用open方法
      login.open()
    })
  </script>

</body>

</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/791419.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vscode c++可以找到声明却无法自动补全

这个问题折磨了我将近一个月&#xff0c;今天终于被解决了&#xff0c;特此记录 情景再现 事情的起因是我在学习华为的Ascend C算子&#xff0c;需要编写C代码。关于怎么下载库文件怎么编译之类的不是本文的重点&#xff0c;重点是自动补全。 我已经拿到库文件了&#xff0c…

力扣题解(设计跳表)

1206.设计跳表 已解答 不使用任何库函数&#xff0c;设计一个 跳表 。 跳表 是在 O(log(n)) 时间内完成增加、删除、搜索操作的数据结构。跳表相比于树堆与红黑树&#xff0c;其功能与性能相当&#xff0c;并且跳表的代码长度相较下更短&#xff0c;其设计思想与链表相似。 …

Linux文件编程应用

目录 一、实现cp命令 二、修改程序的配置文件 三、写一个整数/结构体到文件 1.写一个整数到文件 2.写一个结构体到文件 四、写结构体数组到文件 我们学习了文件编程的常用指令以及了解文件编程的基本步骤后&#xff0c;试着来写一些程序实现某些功能。&#xff08;没有学…

oracle哪些后台进程不能杀?

oracle 有很多的后台进程&#xff0c;在遇到特殊情况的时候如锁表&#xff0c;如果等待的是一个后台进程&#xff0c;那这时就需要考量是不是能杀掉这个后台进程&#xff1f;杀掉这个后台进程会不会引起实例崩溃&#xff1f;本着实践出真知&#xff0c;本文针对oracle 11g&…

昇思25天学习打卡营第23天 | Pix2Pix实现图像转换

内容介绍&#xff1a; Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c;该模型是由Phillip Isola等作者在2017年CVPR上提出的&#xff0c;可以实现语义/标签到真实图片、灰…

二分法求函数的零点 信友队

题目ID&#xff1a;15713 必做题 100分 时间限制: 1000ms 空间限制: 65536kB 题目描述 有函数&#xff1a;f(x) 已知f(1.5) > 0&#xff0c;f(2.4) < 0 且方程 f(x) 0 在区间 [1.5,2.4] 有且只有一个根&#xff0c;请用二分法求出该根。 输入格式 &#xff08;无…

政安晨:【Keras机器学习示例演绎】(五十三)—— 使用 TensorFlow 决策森林进行分类

目录 简介 设置 准备数据 定义数据集元数据 配置超参数 实施培训和评估程序 实验 1&#xff1a;使用原始特征的决策森林 检查模型 实验 2&#xff1a;目标编码决策森林 创建模型输入 使用目标编码实现特征编码 使用预处理器创建梯度提升树模型 训练和评估模型 实验…

从零开始学习嵌入式----C语言框架梳理与后期规划

目录 一、环境搭建. 二、见解 三、C语言框架梳理 四、嵌入式学习规划流程图&#xff08;学习顺序可能有变&#xff09; 一、环境搭建. C语言是一门编程语言&#xff0c;在学习的时候要准备好环境。我个人比较喜欢用VS,具体怎么安装请百度。学习C语言的时候&#xff0c;切忌…

Spring中如何操作Redis

Spring毕竟是Java中的一个主流框架&#xff0c;如何在这个框架中使用Redis呢&#xff1f; 创建项目并引入相关依赖 然后进行创建。 至此就将Redis的相关依赖引入进来了。 编写Redis配置 将application.properties修改成application.yml 然后编写如下配置&#xff1a; spr…

各向异性含水层中地下水三维流基本微分方程的推导

各向异性含水层中地下水三维流基本微分方程的推导 参考文献&#xff1a; [1] 刘欣怡,付小莉.论连续性方程的推导及几种形式转换的方法[J].力学与实践,2023,45(02):469-474. 文章链接 水均衡的基本思想&#xff1a; ∑ 流 入 − ∑ 流 出 Δ V \sum 流入-\sum 流出\Delta V ∑…

ArduPilot开源飞控之AP_Mount_Siyi

ArduPilot开源飞控之AP_Mount_Siyi 1. 源由2. 框架设计2.1 类和继承2.2 公共方法2.3 保护方法2.4 私有成员和方法2.5 解析状态2.6 重要成员变量 3. 重要方法3.1 AP_Mount_Siyi::init3.2 AP_Mount_Siyi::update3.3 AP_Mount_Siyi::read_incoming_packets3.4 AP_Mount_Siyi::proc…

LabVIEW实现LED显示屏视觉检测

为了满足LED显示屏在生产过程中的严格质量检测需求&#xff0c;引入自动化检测系统是十分必要的。传统人工检测方式存在检测强度高、效率低、准确性差等问题&#xff0c;自动化检测系统则能显著提高检测效率和准确性。视觉检测系统的构建主要包含硬件和软件两个部分。 视觉系统…

深度学习论文: LLaMA: Open and Efficient Foundation Language Models

深度学习论文: LLaMA: Open and Efficient Foundation Language Models LLaMA: Open and Efficient Foundation Language Models PDF:https://arxiv.org/pdf/2302.13971.pdf PyTorch: https://github.com/shanglianlm0525/PyTorch-Networks 1 概述 本文介绍了LLaMA&#xff0…

一二三应用开发平台应用开发示例(7)——文档功能实现示例

概述 在完成文件夹配置工作后&#xff0c;接下来配置文档管理系统最核心的管理对象“文档”。 依旧是使用平台低代码配置工作来配置&#xff0c;配置流程跟文件夹的配置是相同的&#xff0c;以下简要说明&#xff0c;重点是新涉及到的功能或注意点。 创建实体 配置模型属性 …

【Dison夏令营 Day 15】 Python 鸡蛋捕手

在本次课程中&#xff0c;我们使用 Python 创建了经典的 "抓蛋 "游戏。在这个游戏中&#xff0c;每抓到一个鸡蛋就能赢得 10 分&#xff0c;而每掉落一个鸡蛋就会损失一条命。 小时候&#xff0c;我们都玩过 "抓鸡蛋 "游戏。我们使用海龟软件包在 Python …

【linux】阿里云centos配置邮件服务

目录 1.安装mailx服务 2./etc/mail.rc 配置增加 3.QQ邮箱开启smtp服务&#xff0c;获取授权码 4.端口设置&#xff1a;Linux 防火墙开放端口-CSDN博客 5.测试 1.安装mailx服务 yum -y install mailx 2./etc/mail.rc 配置增加 #邮件发送人 set from924066173qq.com #阿里…

windows USB 设备驱动开发-USB电源管理(一)

符合通用串行总线 (USB) 规范的 USB 设备的电源管理功能具有一组丰富而复杂的电源管理功能。 请务必了解这些功能如何与 Windows 驱动程序模型 (WDM) 交互&#xff0c;特别是 Microsoft Windows 如何调整标准 USB 功能以支持系统唤醒体系结构。 基于内核模式驱动程序框架的 US…

android13 rom 开发总纲说明

1. 这里是文章总纲&#xff0c;可以在这里快速找到需要的文章。 2. 文章一般是基于标准的android13&#xff0c;有一些文章可能会涉及到具体平台&#xff0c;例如全志&#xff0c;瑞芯微等一些平台。 3.系统应用 3.1系统应用Launcher3桌面相关&#xff1a; 3.2系统应用设置S…

NLP入门——词袋语言模型的搭建、训练与预测

卷积语言模型实际上是取了句子最后ctx_len个词作为上下文输入模型来预测之后的分词。但更好的选择是我们做一个词袋&#xff0c;将所有分词装在词袋中作为上下文&#xff0c;这样预测的分词不只根据最后ctx_len个分词&#xff0c;而是整个词袋中的所有分词。 例如我们的序列是&…

绝对值不等式运用(C++)

货仓选址 用数学公式表达题意&#xff0c;假设有位置a1~an,假设选址在x位置处&#xff0c;则有&#xff1a; 如何让这个最小&#xff0c;我们把两个式子整合一下&#xff0c;利用绝对值不等式&#xff1a; 我们知道&#xff1a; 如下图所示&#xff1a;到A&#xff0c;B两点&…