美文网首页
Class的基本语法和继承

Class的基本语法和继承

作者: 铜牛彦祖 | 来源:发表于2018-07-02 18:15 被阅读0次

    JS引擎是一个大的工厂,
    工厂的专家制作出了Object.prototyp产品
    在这个产品的基础上又制造出了Function.prototype
    在这个原型的基础上制造除了两个非常厉害的机器 Object函数和Function函数
    Object函数用来制造队形
    Function函数用来制造函数
    比如制做一个空的数组[]这么一个对象
    在对象身上都有一个proto这么一个属性,用来指明这个对象的原型是谁
    在每个对象的原型身上又有constructor这个属性,用来表明它的构造函数是谁

    // 在ES5下通常我们会这么写
    const Meizi = function(a,b){
      this.a = a;
      this.b = b;
      return this;
      }
    Meizi.prototype = {
      constructor:Meizi,
      print: function(){
        console.log(this.a+' '+this.b)
      }
     }
    const Meizi  = new Meizi ('hello','world').print();
    
    // 用class改写
    class Meimei{
      constructor(a,b) {
        this.a = a,
        this.b = b
        return this;
      }
      print() {
        console.log(this.a+' ' +this.b)
      }
    }
    const Meizi = new Meimei('hello','world').print();
    console.log(typeof Meimei);//function
    

    1.Meizi 中的constructor方法是构造方法,
    this关键字则代表实例对象。也就是说,ES5
    的构造函数Meizi ,对应ES6的Meizi 这个类的构造方法。

    2.Meizi 这个类除了构造方法,还定义了一个print方法。
    注意,定义“类”的方法的时候,前面不需要加上function
    这个关键字,直接把函数定义放进去就可以了。另外,方法之间
    不需要逗号分割,加了会报错。

    3.构造函数的prototype属性,在ES6的“类”上面继续存在。而且类的所有方法都
    定义在类的prototype属性上面

    console.log(Meizi.prototype)
    

    4.定义在类中的方法都是不可以枚举的

    console.log(Object.keys(Meizi.prototype))//[]
    

    5 constructor 方法是类的默认方法,通过new命令生成对象的实例时,自动调用该方法。一个类必须有constrctor方法,
    如果没有显式定义,一个空的constructor方法会被默认添加。

    6.生成类的实例对象的写法,与ES5完全一样,也是使用new命令。
    如果忘记加上new,像函数那样调用class,将会报错

    class的继承相关知识

    • 子类继承父类 使用extends关键字
    • 为父类指定静态方法,使用static方法名字

    super

    • 在构造函数中可以当一个函数来使用,相当于调用父类的构造函数
    • 在原型方法中,可以当一个对象来使用,相当于父类的原型对象,并且
      会自动绑定到this到子类上

    Class的继承

    子类继承父类 使用extends关键字
    为父类指定静态方法,使用static方法名字

    super

    • 在构造函数中可以当一个函数来使用,相当于调用父类的构造函数
    • 在原型方法中,可以当一个对象来使用,相当于父类的原型对象,并且
      会自动绑定this到子类上
    const canvas = document.querySelector('#canvas');
        
        const ctx = canvas.getContext('2d');
        
        const w = canvas.width = 600;
        const y = canvas.height = 400;
        
        class Ball {
            constructor(x,y,r) {
                this.x = x;
                this.y = y;
                this.r = r;
                this.color = `rgb(${~~Ball.rpFn([55,255])},
                ${~~Ball.rpFn([55,255])},${~~Ball.rpFn([55,255])})`;//两个波浪线可以看作Math.floor()的偷懒写法
                return this;
            }
            render(ctx){ //接收一个参数:绘图环境
                ctx.save();
                ctx.translate(this.x,this.y);
                ctx.fillStyle = this.color;
                ctx.beginPath();
                ctx.arc(0,0,this.r,0,2*Math.PI);
                ctx.fill();
                ctx.restore();
                return this;
            }
            //静态方法
            static rpFn(arr) { //Ball.rpFn([1,10])
                let max = Math.max(...arr),
                    min = Math.min(...arr);
                return Math.random()*(max - min) + min;
            }
        }
        //const ball = new Ball(100,100,30).render(ctx);
        
        
        
        //什么都不写就代表子类完全的继承了父类,但这么写是没有意义的
        //class SuperBall extends Ball {}
        
        
        
        //继承
        class SuperBall extends Ball {
            constructor(x,y,r){
                super(x,y,r);//super调用完毕就相当于子类已经继承了父类的所有属性
                             //在没调用super之前,子类是没有自己的this的
                //纵向速度
                this.vy = SuperBall.rpFn([2,4]);
                //重力加速度
                this.g = SuperBall.rpFn([0.2,0.4]);
                
                this.a = 0;
                return this;
            }
            
            //子类的原型方法
            move(ctx){
    
                //super(); //报错
    
                this.y += this.vy
                this.vy += this.g
                
                let current = this.vy * -0.75
                
                if(this.y+this.r >= ctx.canvas.height) {
                    this.y = ctx.canvas.height - this.r
                    
                    if(Math.abs(current - this.a) < 0.01) return false;
                    
                    //为了让这个小球反弹回去
                    this.a = this.vy *= -0.75
                    
                    
                }
                
                ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height)
                
                //这里的super指向的是父类的原型对象
                super.render(ctx);
                return true;
            }
        };
        //const ball = new SuperBall(100,100,30).render(ctx);
        
        let ball,timer;
        
        canvas.onclick = function (e){
          window.cancelAnimationFrame(timer)
          let x = e.offsetX, y = e.offsetY;
          let r = ~~Ball.rpFn([25,55]);
          
          //为了点击画布只新建一个小球,绘制之前先清除一下画布
          ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height)
          ball = new SuperBall(x,y,r).render(ctx);
          
          ballMove();
          
        }
        
        function ballMove() {
          timer = window.requestAnimationFrame(ballMove);
          
          if(!ball.move(ctx)){
            window.cancelAnimationFrame(timer)
          }
        }
    

    以下是其他资料笔记

    //基本定义和生成实例
    class Parent {
        constructor(name='mukewang'){
            this.name = name;
        }
    }
    let v_parent = new Parent('v');
    console.log('构造函数和实例',v_parent)
    

    继承

    class Parent {
        constructor(name='mukewang'){
            this.name = name;
        }
    }
    class Child extends Parent{
    
    }
    
    console.log('继承',new Child())
    

    继承传递参数

    class Parent {
        constructor(name='mukewang'){
            this.name = name;
        }
    }
    class Child extends Parent{
        constructor(name='child'){
            //覆盖父函数的name
            super(name);
    
            //定义自己的属性,一定要放在super之后
            this.type = 'child';
        }
    }
    
    console.log('继承传递参数',new Child('hello'))
    

    gettter setter

    class Parent {
        constructor(name='mukewang'){
            this.name = name;
        }
        
        //下面是属性
        get longName(){
            return 'mk'+this.name
        }
        set longName(value) {
            this.name = value;
        }
    }
    let v = new Parent();
    console.log('getter',v.longName);
    v.longName='hello';//赋值就是setter操作
    console.log('setter',v.longName)
    

    静态方法

    class Parent {
        constructor(name='mukewang'){
            this.name = name;
        }
        static tell(){
            console.log('tell');
        }
    }
    Parent.tell();
    

    静态属性

    
    class Parent {
        constructor(name='mukewang'){
            this.name = name;
        }
        static tell(){
            console.log('tell');
        }
        
    }
    Parent.type = 'test'
    console.log('静态属性',Parent.type)
    

    相关文章

      网友评论

          本文标题:Class的基本语法和继承

          本文链接:https://www.haomeiwen.com/subject/jgqsyftx.html