感谢b站up主技术蛋老师ES6怎么写class的精彩视频分享!本博客内容及图片均来自于此视频
动机
最近在学习 vue 2 源码-响应式原理中涉及到observer类创建构造函数和实例的乱糟糟知识点,想弄清楚是怎么事,找来技术蛋老师讲解的视频研究一下。
用 class 做一个 废话生成器
<input type="text">
<button class="button_1st">一级废话</button>
<button class="button_2nd">二级废话</button>
<p></p>
class实战开发一个网页:input标签可以让用户输入内容,两个按钮让用户输入内容以后结合内容生成一句废话,最后把整合好的内容输出到p标签里面。
JS实现:把所有标签用变量存储起来,用面向对象思维开发,
<script>
const input = document.querySelector('input'),
button_1st = document.querySelector('.button_1st'),
button_2nd = document.querySelector('.button_2nd'),
p = document.querySelector('p');
</script>
废话生成器是整合了多个功能的东西,也就是封装了很多代码,这些封装起来的代码们,有些表示废话生成器的属性,有些表示废话生成器的方法功能,这样的代码会更好操作,封装起来的这些代码就把它们称为一个类
创建 类
| 对比 | 内容 | 备注 |
|---|---|---|
| 构造函数 | new 生成实例 | |
| class 类 | new 生成实例 | 与构造函数相似 |
constructor方法 | 每次new的时候就会触发这个方法 | class 类自带 |
extends关键词 | 用于继承 | class 类自带 |
super关键词 | 子类不需要写重复代码 直接用 super调用 | 在子类constructor里写this之前一定要写super |
static关键词 | 不需要添加实例创建方法 | 用 类 调用静态方法 |
类 与 构造函数 乃为同门师兄,也就可以new一个空实例:
class Bullshit {}
const bullshit = new Bullshit();
constructor 方法
接下来就是给class添加属性,这些属性是每次生成实例都会各自添加的,即让每个实例都有自己特有的属性,都享有同一套代码。
用class里面的constructor方法,每次new的时候就会触发这个方法。
class Bullshit {
constructor(text, color){ // 每次 new 的时候就会触发这个方法
this.text = text; // 废话内容
this.color = color; // 字体颜色
}
}
实例中也传入参数:
const bullshit = new Bullshit('我知道', '#00a1d6');
自定义 方法
在类中自定义方法不需要写 function 关键字,直接干;添加触发按钮的事件:
class Bullshit {
constructor(text, color){ // 每次 new 的时候就会触发这个方法
this.text = text; // 废话内容
this.color = color; // 字体颜色
}
show(){
p.innerHTML = this.text + input.value;
p.style.color = this.color;
}
}
button_1st.addEventListener('click', ()=>{
const bullshit = new Bullshit('我知道', '#00a1d6'); // new时传入参数
bullshit.show();
});
此时,点击一级废话按钮,会执行一个废话实例,并执行自己的show方法,把自己的text属性和输入内容结合一起,就会显示如下:
extends继承
如果以上实现了的 一级废话 按钮的类,直接复制那就不好玩了,因为 类 提供一个可以用于继承的关键词:extends
创建一个 废话子类 继承 废话父类,并给 二级废话 按钮添加点击事件:
class Son_of_Bullshit extends Bullshit{}
button_2nd.addEventListener('click', ()=>{
const son_of_bullshit = new Son_of_Bullshit('你知道', '#f85b88'); // new时传入参数
son_of_bullshit.show();
});
额外添加属性
如果把额外添加的属性直接写在子类constructor方法中,会覆盖原来父类的constructor方法:
所以在子类constructor里写this之前一定要写super:
class Son_of_Bullshit extends Bullshit{
constructor(fontSize){
super(text, color); // super 前
this.fontSize = fontSize; // this 后 自定义属性
}
show(){ // 改写 自定义方法
p.innerHTML = this.text + input.value;
p.style.color = this.color;
p.style.fontSize = this.fontSize;
}
}
static 静态方法
class Bullshit {
static welcome_tips(){
return '温馨提示:您这是在说废话';
}
constructor(text, color){
this.text = text; // 废话内容
this.color = color; // 字体颜色
}
- 点击
p标签,显示温馨提示,不再额外添加按钮:
p.addEventListener('click', ()=>{
Bullshit.welcome(); // 用 类 调用静态方法
});
// 点击以后,类 调用静态方法,再把另一个静态方法的内容赋值过来
setter 和 getter
class 也把 setter 和 getter两个特殊功能的访问器属性给封装起来了:
// set 标识符
set extra(value){
this.value = value; // 添加一个参数
// 把参数赋值给实例的value属性 并把value属性值加在p标签内容里
p.innerHTML += this.value;
}
在鼠标点击事件里属性设置:
button_1st.addEventListener('click', ()=>{
const bullshit = new Bullshit('我知道', '#00a1d6');
bullshit.show();
bullshit.extra = '儿子';
});
用getter告诉用户哪里是废话:
get extra(){
return `这些是废话:${this.text}, ${this.value}`;
}