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)
网友评论