ES之Class

类和构造函数区别

class Person{
      constructor(name,age) {
        this.name=name;
        this.age=age;
        // 这样子的speak方法就不是共享的
        //this.speak=()=>{};
      }
      speak(){
        console.log('speak');
      }
      //run(){}
    }
    console.log(typeof Person);//function
    // 本质上是下面的内容,但是我们平时上面写比较方便且直观
    console.log(Person.prototype.speak);
    Person.prototype.run=function (){};

    // function Person(name,age){
    //   this.name=name;
    //   this.age=age;
    //   // 这样子的speak方法就不是共享的
    //   //this.speak=()=>{};
    // }
    //
    // // 需要在其原型上添加方法才是共享的
    // Person.prototype.speak=function (){};

Class的两种定义形式

  • 声明形式
  • 表达式形式
// 1.声明形式
    // class Person{
    //   constructor() {}
    //   speak(){}
    // }

    // 2.表达式形式
    // 构造函数
    // function Person(){}
    // 我们可以把匿名函数赋值给一个变量/常量
    // const Person=function (){}

    // 类的表达式形式
    // 我们可以把匿名类赋值给一个变量/常量
    // const Person=class {
    //   constructor() {
    //     console.log('constructor');
    //   }
    //   speak(){}
    // };
    // new Person();
    // 定义即被调用立即执行
    (function (){
      console.log('func');
    })();
    new (class{
      constructor() {
        console.log('constructor');
      }
    })();

 

实例属性、静态方法和静态属性

// 实例方法和实例属性
    class Person{
      age=0;
      sex='male';
      getSex=function (){
        return this.sex;
      }
      // 实例对象的方法
      speak(){
        console.log('speak');
      }
      constructor(name,sex) {
        this.name=name;
        this.sex=sex;
      }
      // 静态方法
      static speak(){
        console.log('人类可以说话');
        console.log(this);
      }
      // 不要这么写,有兼容性问题
      // 静态属性
      // static version='1.0';

      // 通常这样写
      static getVersion(){
        return '1.0';
      }
    }
    // 静态方法
    // Person.speak=function (){
    //   console.log('人类可以说话');
    //   console.log(this);
    // }
    // 静态属性
    // Person.version='1.0';
    const p=new Person('Alex','female');
    console.log(p);
    p.speak();
    // 静态方法
    Person.speak();
    console.log(Person.getVersion());

私有属性和方法

// class Person{
    //   constructor(name) {
    //     this._name=name;
    //   }
    //   speak(){
    //     console.log('speak');
    //   }
    //   getName(){
    //     return this._name;
    //   }
    // }
    // const p=new Person('jessica');
    // console.log(p.getName());
    // p.speak();
    // // 模拟私有属性和方法
    // // 1._开头表示私有(约定)
    // console.log(p.getName());

    // 2.将私有属性和方法移出类
    (function () {
        let name = '';

        class Person {
            constructor(username) {
                name = username;
            }

            speak() {
                console.log('speak');
            }

            getName() {
                return name;
            }
        }

        window.Person = Person;
    })();
    (function () {
        const p = new Person('Alex');
        console.log(p.name);//undefined
        console.log(p.getName());//Alex
    })();

继承extends

class Person{
        constructor(name,sex) {
            this.name=name;
            this.sex=sex;
            this.say=function (){
                console.log('say');
            };
        }
        speak(){
            console.log('speak');
        }

        static speak(){
            console.log('static speak');
        }
    }
    Person.version='1.0';
    class Programmer extends Person{
        constructor(name,sex,feature) {
            super(name,sex);
            this.feature=feature;
        }
        // 同名覆盖
        speak() {
            console.log('Programmer speak');
        }

        static speak(){
            console.log('Programmer static speak');
        }
    }
    Programmer.version='2.0';
    const zs = new Programmer('zs', '男','秃头');
    console.log(zs.name);
    console.log(zs.sex);
    console.log(zs.feature);
    zs.say();
    zs.speak();
    Programmer.speak();
    console.log(Programmer.version);

super

  • 作为函数调用
  • 作为对象调用
  • 注意事项(必须显式注明是函数调用还是对象调用)
// super作为对象使用
    // 在构造方法或一般方法中使用
    // super代表父类的原型对象 Person.prototype
    // 所以定义在父类实例上的方法或属性,是无法通过super调用的
    // 通过super调用父类的方法时,方法内部的this指向当前的子类实例
    class Person{
        constructor(name) {
            this.name=name;
            console.log(this);
        }
        speak(){
            console.log('speak');
            console.log(this);
        }

    }
    class Programmer extends Person{
        constructor(name,feature) {
            super(name);
            this.feature=feature;
            console.log(super.name);
            super.speak();
        }
        speak(){
            super.speak();
            console.log('Programmer speak');
        }
    }

    new Person();
    new Programmer();

 

class Person{
        constructor(name) {
            this.name=name;
            //console.log(this);
        }
        speak(){
            console.log('speak');
            //console.log(this);
        }
        static speak(){
            console.log('Person speak');
            console.log(this);
        }
    }
    class Programmer extends Person{
        constructor(name,feature) {
            super(name);
            this.feature=feature;
            console.log(super.name);
            super.speak();
        }
        speak(){
            super.speak();
            console.log('Programmer speak');
        }

        // 静态方法中使用
        // 指向父类,而不是父类的原型对象
        // 通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例
        static speak(){
            super.speak();
            console.log('Programmer speak');
        }
    }

    Programmer.speak();

Class的应用

幻灯片的切换


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Class 的应用</title>
    <link rel="stylesheet" href="./slider.css" />
  </head>
  <body>
    <div class="slider-layout">
      <div class="slider">
        <div class="slider-content">
          <div class="slider-item">
            <a href="javascript:;"
              ><img src="./imgs/1.jpg" alt="1" class="slider-img"
            /></a>
          </div>
          <div class="slider-item">
            <a href="javascript:;"
              ><img src="./imgs/2.jpg" alt="1" class="slider-img"
            /></a>
          </div>
          <div class="slider-item">
            <a href="javascript:;"
              ><img src="./imgs/3.jpg" alt="1" class="slider-img"
            /></a>
          </div>
          <div class="slider-item">
            <a href="javascript:;"
              ><img src="./imgs/4.jpg" alt="1" class="slider-img"
            /></a>
          </div>
        </div>
      </div>
    </div>

    <script src="./base.js"></script>
    <script>
      // console.log(BaseSlider);

      class Slider extends BaseSlider {
        constructor(el, options) {
          super(el, options);

          this._bindEvent();
        }

        _bindEvent() {
          document.addEventListener('keyup', ev => {
            // console.log(ev.keyCode);
            if (ev.keyCode === 37) {
              // ←
              this.prev();
            } else if (ev.keyCode === 39) {
              // →
              this.next();
            }
          });
        }
      }
      new Slider(document.querySelector('.slider'), {
        initialIndex: 1,
        animation: true,
        speed: 1000
      });
    </script>
  </body>
</html>
/* css reset */
* {
  padding: 0;
  margin: 0;
}
a {
  text-decoration: none;
  outline: none;
}
img {
  vertical-align: top;
}

/* layout */
.slider-layout {
  width: 80%;
  height: 420px;
  margin: 0 auto;
}

/* slider */
.slider,
.slider-content,
.slider-item,
.slider-img {
  width: 100%;
  height: 100%;
}
.slider {
  overflow: hidden;
}
.slider-item {
  float: left;
}
.slider-animation {
  transition-property: transform;
  transition-duration: 0ms;
}
// 默认参数
const DEFAULTS = {
    // 初始索引
    initialIndex: 0,
    // 切换时是否有动画
    animation: true,
    // 切换速度,单位 ms
    speed: 300
};
// base
const ELEMENT_NODE = 1;
const SLIDER_ANIMATION_CLASSNAME = 'slider-animation';

class BaseSlider {
    constructor(el, options) {
        console.log(options)
        if (el.nodeType !== ELEMENT_NODE)
            throw new Error('实例化的时候,请传入 DOM 元素!');

        // 实际参数
        this.options = {
            ...DEFAULTS,
            ...options
        };

        const slider = el;
        const sliderContent = slider.querySelector('.slider-content');
        const sliderItems = sliderContent.querySelectorAll('.slider-item');

        // 添加到 this 上,为了在方法中使用
        this.slider = slider;
        this.sliderContent = sliderContent;
        this.sliderItems = sliderItems;

        this.minIndex = 0;
        this.maxIndex = sliderItems.length - 1;
        this.currIndex = this.getCorrectedIndex(this.options.initialIndex);

        // 每个 slider-item 的宽度(每次移动的距离)
        this.itemWidth = sliderItems[0].offsetWidth;

        this.init();
    }

    // 获取修正后的索引值
    // 随心所欲,不逾矩
    getCorrectedIndex(index) {
        if (index < this.minIndex) return this.maxIndex;
        if (index > this.maxIndex) return this.minIndex;
        return index;
    }

    // 初始化
    init() {
        // 为每个 slider-item 设置宽度
        this.setItemsWidth();

        // 为 slider-content 设置宽度
        this.setContentWidth();

        // 切换到初始索引 initialIndex
        this.move(this.getDistance());

        // 开启动画
        if (this.options.animation) {
            this.openAnimation();
        }
    }

    // 为每个 slider-item 设置宽度
    setItemsWidth() {
        for (const item of this.sliderItems) {
            item.style.width = `${this.itemWidth}px`;
        }
    }

    // 为 slider-content 设置宽度
    setContentWidth() {
        this.sliderContent.style.width = `${
      this.itemWidth * this.sliderItems.length
    }px`;
    }

    // 不带动画的移动
    move(distance) {
        this.sliderContent.style.transform = `translate3d(${distance}px, 0px, 0px)`;
    }

    // 带动画的移动
    moveWithAnimation(distance) {
        this.setAnimationSpeed(this.options.speed);
        this.move(distance);
    }

    // 设置切换动画速度
    setAnimationSpeed(speed) {
        this.sliderContent.style.transitionDuration = `${speed}ms`;
    }

    // 获取要移动的距离
    getDistance(index = this.currIndex) {
        return -this.itemWidth * index;
    }

    // 开启动画
    openAnimation() {
        this.sliderContent.classList.add(SLIDER_ANIMATION_CLASSNAME);
    }

    // 关闭动画
    closeAnimation() {
        this.setAnimationSpeed(0);
    }

    // 切换到 index 索引对应的幻灯片
    to(index) {
        index = this.getCorrectedIndex(index);
        if (this.currIndex === index) return;

        this.currIndex = index;
        const distance = this.getDistance();

        if (this.options.animation) {
            return this.moveWithAnimation(distance);
        } else {
            return this.move(distance);
        }
    }

    // 切换上一张
    prev() {
        this.to(this.currIndex - 1);
    }

    // 切换下一张
    next() {
        this.to(this.currIndex + 1);
    }

    // 获取当前索引
    getCurrIndex() {
        return this.currIndex;
    }
}

素材:1 2 3 4.jpg 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值