JS进阶-原型

07-16 474阅读

学习目标:

  • 掌握原型

    学习内容:

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

    原型:

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

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

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

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

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

    JS进阶-原型

    原型
    
    
      
        // 构造函数  公共的属性和方法 封装到 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)
      
    
    

    JS进阶-原型

    • 小结
      1. 原型是什么?

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

      1. 原型的作用是什么?

      共享方法。

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

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

      实例化的对象。

      • 原型-this指向

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

        构造函数和原型的this指向
        
        
          
            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
          
        
        
        • 练习
           练习-给数组扩展方法
          
          
            
              //自己定义 数组扩展方法 求和  和  最大值
              //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())
            
          
          

          constructor属性:

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

          作用:该属性指向该原型对象的构造函数,简单理解,就是指向我的爸爸,我是有爸爸的孩子。

          JS进阶-原型

          • 使用场景

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

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

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

             constructor属性
            
            
              
                  // 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
              
              
            
            
            • 小结
              1. constructor 属性的作用是什么?

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


              对象原型:

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

              原型对象的属性和方法,就是因为对象有_proto_原型的存在。

              JS进阶-原型

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

                    JS进阶-原型


                    原型继承:

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

                    原型继承
                    
                    
                      
                        //继续抽取  公共的部分放到原型上
                        // 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)
                      
                    
                    

                    原型链:

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

                    JS进阶-原型

                    原型链
                    
                    
                      
                        // 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
                      
                    
                    

                    JS进阶-原型

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

                      综合案例:

                      
                      
                        
                        
                        综合案例-消息提示对象封装
                        
                          .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;
                          }
                        
                      
                      
                        删除
                        登录
                        
                        
                          //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 = `
                            
                            ${title} x
                            ${message}
                          
                            
                            `
                            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()
                          })
                        
                      
                      
                      
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]