JS进阶-原型

学习目标:

  • 掌握原型

学习内容:

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

原型:

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

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

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

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

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

javascript 复制代码
<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指向 实例化的对象。

javascript 复制代码
<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>
  • 练习
javascript 复制代码
 <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指向原来的构造函数。

javascript 复制代码
 <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属性,指向创建该实例对象的构造函数。
javascript 复制代码
 <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

  • 练习
javascript 复制代码
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中大多是借助原型对象实现继承的特性。

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>

原型链:

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

javascript 复制代码
<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属性是否出现在某个实例对象的原型链上。

综合案例:

javascript 复制代码
<!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>
相关推荐
An_s3 小时前
rust开发wasm与浏览器(js)交互
javascript·rust·wasm
山河木马4 小时前
GPU自动处理专题4-填充覆盖区域(光栅化)
javascript·webgl·计算机图形学
从零开始的代码生活_4 小时前
C++ 内存管理:从内存分区到 new/delete 底层原理
开发语言·c++·后端
悦儿遥遥雨14 小时前
PXE + Kickstart 无人值守批量部署系统
linux·javascript·nginx
wabs6664 小时前
关于单调栈【力扣739.每日温度的思考】
java·开发语言
AOwhisky4 小时前
Python 学习笔记(第三期)——流程控制核心知识点自测与详解
开发语言·笔记·python·学习·云原生·运维开发·流程控制
清秋4 小时前
全网最全 ECMAScript 攻略( 更新至 ES2026)
前端·javascript·编程语言
Hilaku5 小时前
为什么 AI 写前端时,总是优先选择 React,而不是 Vue?
前端·javascript·程序员
逆向编程5 小时前
Socket异常连接自动清理方案
开发语言
va学弟6 小时前
Java 网络通信编程(10):Channel 和 Selector
java·开发语言