• 类与对象以及原型机制


    抽取对象共用的属性和行为封装成类

    对象:在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象(属性+方法)

    类:泛指某一大类(class)
    对象:通过实例化的一个具体对象

    constructor构造函数

    constructor()方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过new命令生成对象实例时,自动调用该方法

    <script>
    class Father{
       constructor(x,y){
         this.x=x;
         this.y=y;
      }
      info(){
          console.log(this.x+this.y);
       }
    }
    
    var y=new Father(2,4);
    y.info();       //6
    
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    继承(extends)

    子类可以继承父类的一些属性和方法

    super关键字
    super关键字用于访问和调用对象父类上的函数。可以调用父类的构造方法,也可以调用父类的普通函数

    注意:子类在构造函数中使用super,必须放到this前面(必须先调用父类的构造方法,再使用子类的构造方法)

    1.在ES6中,先定义类,才能通过类实例化对象
    2.类里面的共有的属性和方法一定要加this使用

    子类继承父类的构造方法

    <script>
    class Father{
       constructor(x,y){
         this.x=x;
         this.y=y;
      }
      info(){
          console.log(this.x+this.y).
       }
    }
    
    class Son extends Father{
    
    }
    
    var e = new Son(2,4);
    e.info();
    
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    <script>
            class Father{
               constructor(x,y){
                 this.x=x;
                 this.y=y;
              }
              info(){
                  console.log(this.x+this.y);
               }
            }
            
            class Son extends Father{
              constructor(x,y){
    
                  //倘若子类已有构造函数,要想使用父类的方法,需使用super()
                super(x,y);  
              }
            }
            
            var e = new Son(2,4);
            e.info();
            
            </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    子类继承父类的普通方法

    <script>
            class Father{
               money(){
                 return '年薪百万';
    
               }
    
            }
    
            class Son extends Father{
                money(){
                    //继承父类中money()的普通方法
                    console.log(super.money()+'我也可以');
                }
            }
    
    
            var t = new Son();
            t.money();
    
        </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    综合

    class Father{
                constructor(name){
                   this.name=name;
                //    this.age=age;
    
                }
    
                info(){
    
                    return this.name+'今年';
                }
    
            }
    
            class Son extends Father{
                constructor(name,age){
                    super(name);
                    // this.name=name;
                    this.age=age;
    
                }
                info(){
                    console.log(super.info()+this.age+'了');
                }b
    
            }
            var d = new Son('wzm',22);
            d.info();      //wzm今年22
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    ——————————————————
    在ES6之前,对象不是基于类创建的,而是用一种构造函数的特殊函数来定义对象和他们的特征

    构造函数是一种特殊的函数,用来初始化对象,即为对象成员变量赋初始值,它总与new 一起使用

    在js中,使用构造函数要注意:
    1.构造函数用于创建某一类对象,其首字母要大写
    2.构造函数要和new 一起使用才有意义

    new 在执行时会做四件事
    1.在内存中创建一个新的空对象
    2.让this指向这个新对象
    3.执行构造函数里面的代码,给这个新对象添加属性和方法
    4.返回这个新对象(因此构造函数里面不需要return)

    实例成员只能通过实例化对象访问
    静态成员只能通过构造函数访问

    function Start(name,age){
          this.name=name;
          this.age=age;
          this.skill=function(){
               console.log('敲代码')
           }
    }
    
    var g=new Start('wzm',22);
    //动态
    console.log(g.name);   //wzm
    console.log(g.age);    //22
    g.skill();
    //静态
    Start.sex='男';
    console.log(Start.sex)    //男
    console.log(g.sex)      //undefined
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    构造函数在创建对象时存在内存浪费的问题(主要是公共方法引起的)
    创建一个对象就会占用一个内存地址,因此同一构造函数创建的对象,它们不相等

    构造函数原型prototype

    构造函数通过原型分配的函数是所有对象所共享的
    JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象。(这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有)

    一般情况,公共属性定义到构造函数里面,公共方法放到原型对象上

    Start.prototype.skill=function(){
        //解决了内存浪费
        console.log('敲代码')}
    
    • 1
    • 2
    • 3
    • 4
    <script>
            function Start(name,age){
                  this.name=name;
                  this.age=age;
                //   this.skill=function(){
                //        console.log('敲代码')
                //   }
                 console.log(this.name+'今年'+this.age+'了');
            }
            Start.prototype.skill=function(){
                //解决了内存浪费
                console.log('敲代码');
            }
            
            var g=new Start('wzm',22);
            var y=new Start('lzy',18);
    
            //验证是否占用空间
            console.log(g.skill === y.skill)
       </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    原型:一个对象,成为prototype为原型对象
    原型的作用:共享方法

    对象原型_proto_

    对象都会有一个属性_proto_指向构造函数的prototype原型对象,对象能是用构造函数prototype原型对象的属性和方法,就是因为对象有_proto_原型的存在

    对象._proto===构造函数._prototype_    //true
    
    • 1

    1.只要是对象就有_proto_原型,指向原型对象
    2.我们Start原型对象里面的_proto_原型指向的是Object

    Start._prototype_._proto_ === Object._prototype_ //true
    
    Object._prototype_._proto_=null
    
    • 1
    • 2
    • 3

    Start是一个构造函数,有prototype,而prototype是一个对象,是对象就有_proto_原型,指向原型对象

    原型链

    对象._proto===构造函数._prototype_
    
    构造函数._prototype_._proto_ === Object._prototype_
    
    • 1
    • 2
    • 3

    扩展内置对象
    作用:解决构造函数原型对象中没有的方法

    数组求和∑

    //方法一
    Array.prototype.sum=function (){
         var sum=0;   
          for(var  i=0;i<this.length;i++){  
               sum+=this[i];
                 }  
               return sum;
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    //写法二
    Array.prototype={        
      sum:function {                    
            var sum=0;              
     for(var i=0;i<this.length;i++){                    
          sum+=this[i];         
     }          
      return sum;}}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    var arr=[1,2,3];
    console.log(arr.sum())    //6
    
    • 1
    • 2

    注意:方法二行不通,原因会覆盖构造函数原型对象的方法

    Call方法

    作用:
    1.call()可以调用函数
    2.call()可以改变这个函数的this指向,此时函数就指向处理的对象

    function fn(){
         console.log(11)     
         console.log(this)  //Windows对象
         }
         var y={   
          name:'wzm'};
          
          fn.call();   //11
          fn.call(y)   //将fn中的this指向y对象
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    <script>
       function Father (uname,age){
           this.uname=uname;
           this.age=age;
       }
       function Son(uname,age){
          Father.call(this,uname,age);
          //将Father中的this指向Son
       }
       var son=new Son('wzm',22);
       console.log(son);
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    拓展
    改变this指向的其他两种( apply () , bind () )
    apply ()

    var t ={
    name:'wzm'
    }
    
    function fn(arr){
      console.log(arr);
    }
    
    fn.apply(t,['lzy']);
    //注意:传递的参数必须是数组(伪数组)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    案例<求数组中最大的值>

    var f=[];
    var max=Math.max.apply(Math,f);
    console.log(max);
    
    • 1
    • 2
    • 3

    bind()

    fun.bind(被指向函数,参数)
    
    • 1

    注意:参数不一定是数组;
    返回由指定的this值和初始化参数改造的原函数拷贝

       var o={
          name:'wzm';
       }
       function fn(a,b){
           console.log(a+b);
       }
       var f =fn.bind(o)  //{name:'wzm'}
       var f=fn.bind(o,1,2)    //{name:'wzm'},3
       f();
       
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Es6之前,使用构造函数和原型实现面向对象编程
    Es6之后,使用类实现面向对象编程

  • 相关阅读:
    Hybrid Astar 算法剖析和实现(七)
    python项目之AI动物识别工具的设计与实现(django)
    吴恩达深度学习笔记:深度学习引言1.1-1.5
    传感器数据采集:采样定理(奈奎斯特定理)
    python基于PHP+MySQL婚介交友网站的设计与开发
    VScode Invoke-Expression: 无法将参数绑定到参数“Command”,因为该参数为空字符串
    大厂面试题:【SpringBoot篇面试题:1-5题】
    网站登录界面制作(three.js 3D特效背景)+ boostrap导航栏实现 + jQuery移动窗口【附加源代码】
    PCL点云处理之点云转为Mesh模型并保存---方法一 (二百一十)
    uni-app - 树形结构选择器组件(支持单选 / 多选 / 可选择父级 / 弹框形式)树形控件 tree 无限级节点树,树插件完整源码,最好用的组件教程
  • 原文地址:https://blog.csdn.net/zimingyo/article/details/126682296