JS类的使用

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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值