7、class的继承—ES6学习笔记
来源:互联网 发布:欧洲史 知乎 bbc 编辑:程序博客网 时间:2024/06/05 20:33
extends、 static、 super
在ES6中extends关键字,可以很方便的实现子类继承父类,同时static关键字可以为类指定静态方法,以及super关键字可以在子类继承父类的时候,方便的去调用父类原型身上的方法或者静态方法。
本节我们将通过具体的例子来阐述着三个关键字如何使用?
首先我们在html中写了一个简单的canvas画布以及一些简单的样式阴影,这样我们可以很方便的看到这个画布在文档中的位置。
index.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title></title> <style> canvas { box-shadow: 2px 2px 12px rgba(0, 0, 0, 0.5); } </style></head><body> <canvas id="canvas"></canvas> <script src="./js/bundle.js"></script></body></html>
如图所示:
需求:
我们要写一个小球的类,通过实例化这个小球,将小球绘制在画布当中。
并且让小球做一个自由落体的运动。
// 1、获取这个画布const canvas = document.querySelector('#canvas');// 2、获取一下这个画布对应的绘图环境const ctx = canvas.getContext('2d');// 3、初始化两个常量,来指定这个画布的分辨率const w = canvas.width = 600;const h = canvas.height = 400;// 4、现在我们通过class关键字声明一个Ball小球的类class Ball { /* 5、首先指定一下它的构造函数constructor, 同时化初始化三个参数x,y,r,分别对应小球的横坐标、纵坐标、以及小球的半径 */ constructor(x, y, r){ this.x = x; this.y = y; this.r = r; /* 6、接下来再给小球添加一个color属性,让它随机的等于一个rgb值 这里需要用到一个产生随机数的方法,但是这个方法和绘制小球实际上并没有太多的关系, 所有我们把这个方法写成Ball类的静态方法,转至第7步 10、 接下来我们做一下字符串的拼接,这里我就使用Ball类下面的rpFn()函数获取随机数 使用两个~~号去掉小数部分, */ this.color = `rgb(${~~Ball.rpFn([55, 255])}, ${~~Ball.rpFn([55, 255])}, ${~~Ball.rpFn([55, 255])})`; // 11、最后我们return this,这样方便在实例化的时候调到其它的方法 return this; } /* 12、 为了让小球绘制到画布当中,我们在写一个render方法 render方法接收一个参数,就是绘图的环境ctx */ render(ctx){ // 13、首先保存一下绘图环境 ctx.save(); // 14、绘制小球的坐标 ctx.translate(this.x, this.y); // 15、指定一下小球的填充颜色 ctx.fillStyle = this.color; // 16、起始一个新的路径 ctx.beginPath(); // 17、绘制小球的路径 ctx.arc(0, 0, this.r, 0, 2*Math.PI); // 18、给小球填充颜色 ctx.fill(); // 19、恢复一下绘图环境 ctx.restore(); // 20、返回teturn this return this; } /* 7、如何指定静态方法 前面我们已经提了,使用static关键字 这里只需要写上static,然后跟上方法的名字就可以了,这里叫rpFn 给它接收一个参数数组 使用它的时候,如:Ball.rpFn([1, 10]),那么它就可以返回一个1-10之间的随机数 */ static rpFn(arr){ // Ball.rpFn([1, 10]) // 8、 接下来我们就来实现这个函数,首先声明两个变量 // 获取到这个数组的最大值和最小值,使用...作为扩展运算符 let max = Math.max(...arr), min = Math.min(...arr); // 9、返回一组固定区间的随机数 ,这样我们获取随机数的函数就写好了 return Math.random() * (max - min) + min; }}/* 21、声明一个变量,实例测试一下 在坐标100,100的位置,绘制一个半径为30的小球 此时我们发现一个小球就绘制在画布当中了*/// const ball1 = new Ball(100, 100, 30).render(ctx);/* 22、接下来我任然绘制一个小球在画布当中,并且让它做一个自由落体的运动。 那么我们可以肯定接下来绘制的这个小球依然有Ball所有的属性以及绘制 的render方法。 我们声明一个新的类,起名叫SuperBall,它可以先去继承Ball的类, 把它的属性和方法继承过来*/// 子类 继承 父类class SuperBall extends Ball { // 23、此处如果什么都不写,相当于复制了一个Ball类 // 24、接下来我们就给SuperBall指定一些它自己的属性和方法 // 首先写上它的构造函数constructor,这里面依然需要传入x,y,r三个参数 constructor(x, y, r){ /* 25、我们首先要继承x,y,r三个属性, 我们去调用一下父类的构造函数,发现报错了 */ // Ball.call(this, x, y, r); // 报错 找不到this,实际上通过class定义的类在ES6中它是不允许通过函数的方式去调用的, // 也就是说这种写法本身就是错的 // this.color = 'red'; /* 26、那么如何在子类中调用父类的构造函数呢? 在ES6当中提供了一个新的关键字,super super主要有两种用法 第一种:就是在子类继承父类的时候, 在子类的构造函数中可以当成一个函数去使用, 当它当作函数去使用的时候,就相当于调用了父类的构造函数 这里由于要继承x,y,r三个属性,所有要把这三个参数传进去 */ super(x, y, r); //这个时候我们就发现一个小球就绘制在相同的位置了 /* 27、super(x, y, r);调用完成之后,实际上就相当于子类继承了父类构造函数当中的所有的属性, 在ES6中规定在没调用super()函数之前子类是没有自己的this的 */ //纵向的速度vy //28、也就是说当子类继承父类的时候不仅仅是继承属性,还会自动继承静态方法 this.vy = SuperBall.rpFn([2, 4]); this.g = SuperBall.rpFn([0.2, 0.4]); this.a = 0; return this; } // 28、为了让小球动起来,我们再写一个move方法 move(ctx){ // super()在非构造函数中调用时会报错,super()只能在构造函数中调用 // 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; } // 29、清除整个画布大小 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // 30、将绘图打印出来,这里render不是当作函数调用 // super的第二种使用情况: // 如果在原型的方法里使用super,它实际上指向的是父类的原型对象 super.render(ctx); return true; }};// 我们发现一个小球就绘制在了相同的位置了// const ball1 = new SuperBall(100, 100, 30).render(ctx);/*我们想鼠标点击哪里,哪里就出现一个小球,并且呈现自由落体运动*/let ball, timer;canvas.onclick = function (e){ // 31、获取点击画布的鼠标坐标 let x = e.offsetX, y = e.offsetY; // 通过Ball的静态方法来指定一个随机的半径 let r = ~~Ball.rpFn([25, 55]); //33、为了每次点击值产生一个小球,故每次点击之前最画布进行一次清除 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // 32、接受一个实例对象 ball = new SuperBall(x, y, r).render(ctx); // 33、调用一下小球掉下来的方法 ballMove();}function ballMove(){ // 34、用timer变量接收一下动画帧的返回值 timer = window.requestAnimationFrame(ballMove); //35、如果ball.move(ctx)返回了一个false //就清除这个动画帧 if(!ball.move(ctx)){ window.cancelAnimationFrame(timer); }}
我们做一下简单的总结回顾:
首先在Ball这个类中,我们通过static关键字来指定了一个镜静态方法,静态方法实际上就是挂载到类身上的方法,
接下来我们实现了用extends,用子类去继承父类,并且想给子类去指定一些额外的属性,首先需要通过super关键字调用一下父类的构造函数,这里面想继承那些属性就要把哪些属性当参数传到方法上,
接下来在子类的原型方法当中,如果是super()当作一个函数去调用的时候,就会报错,
此外,在构造函数当中在没使用super()之前是拿不到this 对象的,必须先调用super()才能调用子类的this对象。
接下来在原型的方法当中还有第二种情况,super可以当作一个对象去调用,它实际上指向的是父类原型的对象,并且在调用父类原型身上的方法的时候,会自动的绑定子类的this
子类继承父类 使用extends 关键字
为父类指定静态方法,使用 static 方法名字
super
- 在构造函数中可以当做一个函数来使用,相当于调用父类的构造函数
- 在原型方法中,可以当一个对象类使用,相当于父类的原型对象,并且会自动绑定this到子类上
- 7、class的继承—ES6学习笔记
- 【ES6】class的继承
- ES6 —(Class 的继承)
- ES6 学习笔记 Class
- 6、class的基本使用—ES6学习笔记
- ES6学习笔记之class
- ES6 中 Class 学习笔记
- es6 javascript的Class 类的继承
- ES6 class的继承使用细节
- ES6基础之Class的继承
- JavaScript ES6新的类继承特性学习笔记
- es6笔记7^_^class
- es6笔记7^_^class
- ES6学习笔记(八)--Class
- ES6的学习笔记
- ES6学习笔记-ES6的概念
- ES6学习——class到底是个啥
- es6中class学习
- 函数的四种调用模式(this的指向)
- should use @string resource / android 控件名称
- Go获取类型底层类型
- XORBOOT UEFI工具制作双系统启动引导
- dede增加栏目缩略图 织梦cms增加栏目缩略图2017版方法
- 7、class的继承—ES6学习笔记
- ReactNative开发环境搭建过程及遇到的问题
- 沙箱模式
- openwrt 软件源配置和问题解决
- JAVA Redis缓存实现步骤
- 放羊娃娃的春天-Redis学习笔记
- 闭包缓存
- 浅谈 Express 4.0 Router 模块
- Java注释自动作者与写作时间