es6 class
es6的class 的出现 基本上可以替代了es5的构造函数和原型,使之代码结构上更加简洁。
关键字
- class
- 属性
- 方法
- 继承 extends
- 构造函数 constructor
- 方法重写 override:子类方法覆盖父类,super.父类方法()
- 父类的构造函数 super :子类有构造方法且使用this前,必须使用super()
ES6面向对象 - 类和成员
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES6面向对象 - 类和成员</title>
</head>
<body></body>
<script>
// ES6中: 为了体现主体的概念(对象), 增加了一种结构: 类 class(抽象结构)
// 语法使用没有什么区别
// 1. 定义类(结构): 不会自动运行
// 2. 调用类(实例化)
// 定义类: class + 类名{} 类名: 大驼峰
class Student {}
// 实例化类: 得到具体的对象
new Student();
// 类成员: 直接归属类的{}管理的成员
// 1. 属性: 变量, 保存数据, 但是不要关键字 let, 直接写名字即可, 赋值要用 = 等号
// 2. 方法: 函数, 数据加工, 但是不要关键字 function, 直接写名字即可(自带function)
class Teacher {
// 属性
workId; // 工号, 可以没有值(默认值是: undefined)
age = 0; // 年龄, 可以有初始值: 大家都一样的时候
// 方法
work() {
// this代表: new出来的对象(谁调用 代表谁)
console.log("方法", this);
}
// 方法: 为了保证内存只有一份, 自动进了原型对象
}
// 实例化
const t = new Teacher();
console.log(t);
// 类就当做ES5中的构造函数: 也有原型对象
console.log(Teacher.prototype);
// 类中的属性和方法: new出来的对象, 可以直接使用
console.log(t.workId, t.age);
t.workId = "007";
t.work();
// 总结
// 把ES6的类class, 当成ES5的构造函数即可
// 为了方便: 不需要写this(属性: 也不需要let) 和 function(方法)
// 使用类: 就跟ES5的实例化是一样的
</script>
</html>
ES6面向对象-构造方法constructor
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES6面向对象-构造方法constructor</title>
</head>
<body></body>
<script>
// ES6中有一个特殊的方法: 名字是固定的 constructor(), 当对象new出来之后: 立马会自动调用的方法
class Student {
name;
// 学生应该有姓名和年龄
constructor(name, age) {
console.log("我被执行了");
// 给当前对象添加属性
this.name = name; // 修改属性: name属性(在外面定义没有意义)
this.age = age; // 新增属性: age属性
}
}
// new Student() // 会触发构造函数的执行: new出来对象, 对象自动调用
// 如何给构造方法传参呢? new 类名() , 这个括号()就是在调用constructor(), 用来给constructor传参的
const s = new Student("百里", 20);
console.log(s);
// 构造方法作用: 初始化数据的(以后写类如果要初始化数据: 就要有构造方法constructor(); 如果没有数据要初始化: 不需要这个方法)
// 构造方法: 只有new出来的对象自己调用的权利: 不能手动调用
// s.constructor('妲己', 18)
// Class constructor Student cannot be invoked without 'new'
// 类的constructor方法 不能 被 唤醒 没有 new
// 类的constructor方法只能通过new出来的对象去唤醒(调用)
// 总结
// 构造方法用来初始化数据的: 本质就是ES5的构造函数(只是名字固定为: constructor, 目的就是为了让系统能够自动调用)
</script>
</html>
ES6面向对象 - 继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES6面向对象 - 继承</title>
</head>
<body></body>
<script>
// 继承: 实现代码的复用
// 涉及继承: 项目级别
// 前开设计的时候: 一定会对代码进行分层(找出上下级的关系)
// 教务管理系统: 学生Student\老师Teacher\行政...\教室ClassRoom
// 发现: 学生\老师\行政... 但凡是人,都有共同的内容: 姓名\年龄...数据(属性) 吃喝拉撒(行为: 方法)
// 首先定义一个人类(上级类: 父类)
class Person {
name;
age;
chi() {
console.log(this.name + "正在吃");
}
he() {
console.log(this.name + "正在喝");
}
}
// 定义下级类: 子类: class 子类 extends 父类
class Student extends Person {}
// 实例化子类(父类通常是用来提供公共代码, 不会被实例化)
const s = new Student();
console.log(s);
// 对比一下ES5实现
function Human() {
this.name = undefined;
this.age = undefined;
}
Human.prototype.chi = function () {};
Human.prototype.he = function () {};
// 子类继承
function Teacher() {
// 借调
Human.call(this);
}
// 体现继承
Teacher.prototype.__proto__ = Human.prototype;
const t = new Teacher();
console.log(t);
// 总结
// ES6的继承比ES5简洁方便, 更容易看懂
// ES6继承: 属性被直接拿过来, 方法还在原型对象中: 只能用,不能拿过来
</script>
</html>
ES6面向对象 - Tab栏切换 ( 案例
)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES6面向对象 - Tab栏切换</title>
</head>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
.box {
width: 400px;
height: 300px;
border: 1px solid #ccc;
margin: 100px auto;
}
.hd {
height: 45px;
}
.hd span {
display: inline-block;
/*将行内元素转换成行内块元素,宽高才起作用*/
width: 90px;
background-color: pink;
line-height: 45px;
text-align: center;
cursor: pointer;
}
.hd span.current {
/*交集选择器,标签指定式选择器*/
background-color: purple;
/*紫色*/
}
.bd li {
height: 255px;
background-color: purple;
display: none;
/*设置隐藏*/
}
.bd li.current {
display: block;
/*显示*/
}
</style>
<script src="./js/Tab.js"></script>
<body>
<div class="box" id="box">
<div class="hd">
<span class="current">体育</span>
<span>娱乐</span>
<span>新闻</span>
<span>综合</span>
</div>
<div class="bd">
<ul>
<li class="current">我是体育模块</li>
<li>我的娱乐模块</li>
<li>我是新闻模块</li>
<li>我是综合模块</li>
</ul>
</div>
</div>
</body>
<script>
const tab = new Tab();
console.log(tab);
tab.mouseover();
</script>
</html>
js
/**
* 1. 先定义类: class
* 2. 考虑: 是否存在数据需要初始化: 获取元素, 有初始化,增加一个方法: constructor()构造方法: 构造方法里面的数据,不是给自己用的, 是给其他方法用的(不能使用局部变量), 将数据保存到this,中, 所有方法中的this都是同一个对象
* 2.* 考虑是否有灵活: 传参
* 3. 考虑: 功能问题, 一个功能一个方法, mouseover鼠标移入效果: 一个独立的方法
* */
class Tab {
constructor() {
this.spans = document.querySelectorAll(".hd span");
this.lis = document.querySelectorAll(".bd li");
}
mouseover() {
// 给所有的span做鼠标移入事件
// console.log(this)
// 都用箭头函数的目的: 保证this永远是一个东西
this.spans.forEach((span, index) => {
span.addEventListener("mouseover", () => {
// 排他: 先统一后特殊
// span和li干掉current类
this.spans.forEach((item, i) => {
// item是每个span,i是每个span对应的下标
item.classList.remove("current");
this.lis[i].classList.remove("current");
});
// 当前span和当前li增加current类
span.classList.add("current");
this.lis[index].classList.add("current");
});
});
}
click() {
// 给所有的span做鼠标点击事件
// console.log(this)
// 都用箭头函数的目的: 保证this永远是一个东西
this.spans.forEach((span, index) => {
span.addEventListener("click", () => {
// 排他: 先统一后特殊
// span和li干掉current类
this.spans.forEach((item, i) => {
// item是每个span,i是每个span对应的下标
item.classList.remove("current");
this.lis[i].classList.remove("current");
});
// 当前span和当前li增加current类
span.classList.add("current");
this.lis[index].classList.add("current");
});
});
}
}
ES6面向对象 - 重写override
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES6面向对象 - 重写override</title>
</head>
<body></body>
<script>
// 重写: override, 子类拥有与父类同名的属性或者方法
class Person {
name = "Person";
age = 60;
work() {
console.log(this.name + "种田为生");
}
other() {
console.log("固定被继承方法");
}
}
class Farmer extends Person {
// 重写
// 属性重写: 子类覆盖父类(永远找不到父类的)
name = "Farmer";
// 方法重写: 子类父类都存在, 访问只访问到自己的
work() {
console.log(this.name + "新农民挣钱");
}
}
const f = new Farmer();
console.log(f);
console.log(f.name, f.age); // Farmer 60
f.work(); // 新农民: 只访问到自己
f.other(); // 固定被继承方法
// 总结
// 重写:override, 子类拥有与父类同名的属性或者方法
// 属性重写: 覆盖效果(父类的没了)
// 方法重写: 访问只访问到自己(父类还在)
// 重写作用1: 就是为了"覆盖", 为了让父类的方法,特殊化(应用较多是 老旧系统维护)
</script>
</html>
ES6面向对象 - 重写override - 调用父类被重写方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES6面向对象 - 重写override - 调用父类被重写方法</title>
</head>
<body></body>
<script>
// 方法重写作用1: 完全覆盖父类方法(不用父类的)
// 方法重写作用2: 在父类的基础上做扩展
// 需要在子类重写父类的方法 中: 先调用父类的, 然后再执行自己其他代码
class Person {
work() {
console.log("Person的work方法");
}
}
class Farmer extends Person {
// 重写功能的扩展
work() {
// 明确调用上级的被重写方法: super.被重写方法()
super.work();
console.log("Farmer修改的work方法");
}
}
const f = new Farmer();
f.work();
// 如果是构造方法呢?
// 1. 如果父类有构造方法: 子类可以重写, 但是重写后,必须先保证父类的构造方法运行
class Human {
constructor(name, age) {
this.name = name;
this.age = age;
console.log("Human的构造方法");
}
}
class Student extends Human {
constructor(name, age, stuno) {
// 构造方法一旦被重写: 子类必须调用父类的构造方法(先调用, 后使用this)
// 构造方法很特殊: 类中是固定名字的: constructor(), 所以调用也很特殊: super()
super(name, age);
// 子类只要初始化新的即可(旧的父类做好了)
this.stuno = stuno;
console.log("Student的构造方法");
}
}
// 子类 不重写父类构造方法 之前
// const s1 = new Student('张三', 20)
// console.log(s1)
// 子类 重写父类构造方法 之后
const s2 = new Student("茂春", 16, "007");
console.log(s2);
// 总结
// 重写作用1: 子类覆盖父类(重新来过), 直接重写即可
// 重写作用2: 子类扩展父类, 普通扩展(super.被重写方法名(实参): 可以不调用(覆盖效果)), 如果是构造方法重写: 必须先调用父类的构造方法(super(实参)), 一定要先super(),再做别的事情
</script>
</html>
ES6面对对象 - 元素创建继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES6面对对象 - 元素创建继承</title>
<style>
.element {
width: 200px;
height: 200px;
border-radius: 50%;
border: 10px solid #00ffff;
text-align: center;
font-size: 30px;
line-height: 200px;
overflow: hidden;
float: left;
}
</style>
</head>
<script src="./js/CreateElement.js"></script>
<body></body>
<script>
// 需求:ES6面向对象, 实现动态创建元素
const div = new CreateElement("div", "element", "是我想太多");
div.appendTo("body");
const span = new CreateElement("span", "element", "你总这么说");
span.appendTo("body");
// 放前面
const p = new CreateElement("p", "element", "想太多");
p.insertBefore("body", document.querySelector("div"));
</script>
</html>
ES6面对对象 - 元素创建继承 - 修复缺陷
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES6面对对象 - 元素创建继承 - 修复缺陷</title>
<style>
.element {
width: 200px;
height: 200px;
border-radius: 50%;
border: 10px solid #00ffff;
text-align: center;
font-size: 30px;
line-height: 200px;
overflow: hidden;
float: left;
}
</style>
</head>
<script src="./js/CreateElement.js"></script>
<body></body>
<script>
// 需求:ES6面向对象, 实现动态创建元素
const div = new CreateElement("div", "element", "是我想太多");
div.appendTo("body");
const span = new CreateElement("span", "element", "你总这么说");
span.appendTo("body");
// 放前面
const p = new CreateElement("p", "element", "想太多");
p.insertBefore("body", document.querySelector("div"));
const img = new CreateImg("images/帅哥.png", "element");
img.appendTo("body");
</script>
</html>
js
/**
* 1. 创建类CreateElement
* 2. 考虑: 是否有数据需要初始化: 有, 需要根据用户指定的标签,类名和文本, 创建对应的元素: constructor(标签,类名,文本): 数据保存在this中
* 3. 有什么功能, 就增加什么方法: 一个功能一个方法: appendTo(选择器)
* */
class CreateElement {
constructor(tag, className, txt) {
// 创建元素: 加类 + 加文本
this.ele = document.createElement(tag);
this.ele.className = className;
this.ele.innerHTML = txt;
}
appendTo(selector) {
// 获取父元素
let parent = document.querySelector(selector);
// 给父元素添加孩子
parent.appendChild(this.ele);
}
// 放前面
insertBefore(selector, son) {
let parent = document.querySelector(selector);
parent.insertBefore(this.ele, son);
}
}
// 创建一个图片类:继承CreateElement,修改创建元素的方式(扩展):给元素增加一个src属性
class CreateImg extends CreateElement {
// 重写构造方法
constructor(src, className) {
// 构造方法继承重写:先执行父类的
super("img", className, "");
// 标签是写死的 img,类名是用户传入的,文本:单标签,建议使用空字符串
// 扩展:src属性
// console.log(this)
this.ele.src = src;
}
}