1.类的基本用法
1.1 不需要跟括号来接收参数,每个对象之间不需要逗号连接
1.2 接收参数要constructor来接收,它会自行调用
class User {
constructor (name) {
this.name = name
console.log(123)
}
getName () {
return this.name
}
}
let zs = new User('张三')
console.log(zs.getName()) //张三
2.类和普通构造函数的区别
2.1 在类中定义的方法都会自动绑定到该类的原型上去,这样就不需要手动转了
2.2 在类中定义的方法是不会被遍历的,但是属性可以被遍历,如果需要将方法遍历就需要改方法的特征。
2.3 类是默认在严格模式下运行的。
3.静态属性
3.1 当需要创建一个被所有实例对象使用的属性的,就搞一个静态就是把变量给绑定到类上面,而不是绑定到每个实例上,这样改变一次所有的都会改变。
class User {
static name = '张三'
showName () {
return User.name
}
}
3.2使用静态方法来完成计算最高价格的操作
let data = [
{name: 'js', price: 100},
{name: 'node', price: 200},
{name: 'vue', price: 300},
]
class Lessons {
constructor (data) {
this.model = data
}
name () {
return this.model.name
}
price () {
return this.model.price
}
static createPrice (data) {
return data.map(item => new Lessons(item))
}
static MaxPrice (data) {
return data.sort((a,b) => {
return b.price() - a.price()
},0)
}
}
const lessons = Lessons.createPrice(data)
console.log(Lessons.MaxPrice(lessons)[0].name())
4.使用Symbol保护属性
可以让外部无法访问属性,但在内部和子类中可以使用。
const protecteds = Symbol()
class User {
constructor (name) {
this[protecteds] = {}
this[protecteds].name = name
}
//如果需要外部访问就要定义一个访问器
get name () {
return this[protecteds].name //在内部可以访问该属性
}
}
let obj = new User('张三')
console.dir(obj)
console.log(obj.name)
5.私有属性
在前面加个#就行
只能在内部使用,外部以及子类都不能使用,否则会报错
class User {
constructor (name) {
this.name = name
}
#fun () {
return this.name
}
}
class Admin extends User {
constructor () {
super()
this.#fun()
}
}
let zs = new User('张三')
6.class继承
原理就是用super来代替call,super会调用父类
class User {
constructor (name) {
this.name = name
}
}
class Admain extends User{
constructor (name) {
super(name)
}
}
let zs = new Admain('张三')
console.log(zs.name)
7.使用super()完成多重继承
当使用this时this就只能指向一个对象,这样当需要当前对象和使用对象时就会发生冲突
而super则能很好得解决这个问题,因为它总是指向父类,一级一级的传递
let obj1 = {
name: '张三',
show () {
console.log(this.name)
}
}
let obj2 = {
__proto__: obj1,
name: '李四',
show () {
super.show()
}
}
let obj3 = {
__proto__: obj2,
name: '王五',
show () {
super.show()
}
}
obj3.show()
8.super注意事项
8.1 在子类的constructor中一定要调用super(),否则父类的构造函数就没有参数。
8.2 必须在this之前调用super(),避免被父类里面的this覆盖
9.通过super()调用父类方法完成统计数据
class User {
sum () {
return this.data.reduce((t,c) => {
return t + c.price
}, 0)
}
}
class Admin extends User {
constructor (data) {
super()
this.data = data
}
info () {
return {
totalPrice: super.sum(),
data: this.data
}
}
}
let data = [
{name: 'js', price: 100},
{name: 'node', price: 200},
{name: 'vue', price: 300}
]
let zs = new Admin(data)
console.log(zs.info())
10.使用instanceof来判断是否是某个构造函数的实例
class User {}
class Admin extends User {}
let zs = new Admin()
console.log(zs instanceof User) //true
11.用isPrototypeOf()来判断是否被某个对象继承
class User {}
class Admin extends User {}
let zs = new Admin()
console.log(User.isPrototypeOf(Admin))
12.使用类来完成手风琴菜单效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
width: 100%;
height: 800px;
display: flex;
justify-content: center;
align-items: center;
}
.slide {
width: 300px;
display: flex;
flex-direction: column;
justify-content: space-evenly;
}
dt {
height: 30px;
background-color: #2E3E54;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
.slide dt:first-of-type {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
dd {
height: 100px;
background-color: #F1BC12;
overflow: hidden;
}
.slide dd:last-of-type {
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
</style>
</head>
<body>
<div class="slide s1">
<dt>张三</dt>
<dd>
<div>zhangsan.com</div>
</dd>
<dt>李四</dt>
<dd>
<div>lisi.com</div>
</dd>
<dt>王五</dt>
<dd>
<div>wangwu.com</div>
</dd>
</div>
<script>
class Animation {
constructor(el) {
this.el = el
this.timeOut = 5
this.isShow = true
this.defultHeight = this.height
}
hide(callback) {
this.isShow = false
let time = setInterval(() => {
if(this.height <= 0){
clearInterval(time)
callback && callback()
return
}
//为了解决一直点就一直增加高度的bug所以需要放在结束定时器后面,还得有return
this.height = this.height - 1
}, this.timeOut)
}
show(callback) {
this.isShow = true
let time = setInterval(() => {
if(this.height >= this.defultHeight){
clearInterval(time)
callback && callback()
return
}
this.height = this.height + 1
}, this.timeOut)
}
get height() {
//最后返回出来的是个字符串,做减法时没事,但做加法就不行,所以需要乘1来转为数字
return window.getComputedStyle(this.el).height.slice(0, -2)*1
}
set height(height) {
this.el.style.height = height + 'px'
}
}
class Slide {
constructor (el) {
this.el = document.querySelector(el)
this.links = this.el.querySelectorAll('dt')
this.panels = [...this.el.querySelectorAll('dd')].map(
item => new Panel(item)
)
console.log(this.panels)
this.bind()
}
bind () {
this.links.forEach((item,i) => {
item.addEventListener('click', ()=>{
this.action(i)
})
})
}
action (i) {
Panel.hideAll(Panel.filter(this.panels, i), () => {
this.panels[i].show()
})
}
}
class Panel extends Animation{
static num = 0
static hideAll (items, callback) {
//num大于0的时候说明还有动画在进行
if (Panel.num > 0) return;
items.forEach(
item => {
Panel.num ++
item.hide(() => {
Panel.num --
})
})
callback && callback()
}
static filter (items, i) {
return items.filter((items, index) => index != i)
}
}
let el = new Slide('.s1')
</script>
</body>
</html>