zoukankan      html  css  js  c++  java
  • 深入理解class

    一, class和自定义类型的区别:

      1,类声明不会被提升。

      2,类声明的代码自动运行在严格模式。

      3,类的所有方法都是不可枚举的,而自定的方法必须使用Object.defineProperty来设置。

      4,类的所有方法都没有[[Construct]],因此用new来调用会报错。

      5,调用类构造器不使用new 会报错。

      6,视图在类的内部重写类名会报错。

    二,类的生成器方法

      可以使用 Symbol.iterator来定义生成器方法,来生成类的默认迭代器。

    class Iterator{
        constructor() {
            this.arr = [1,2,3,4];
        }
        *[Symbol.iterator]() {
             yield *this.arr.values();
        } 
    } 
    
    let iter = new Iterator();
    for (let i of iter) {
        console.log(i)
    }

      这样每个实例就都可以使用for of来使用。 

    三, 静态成员

      class中的静态方法 是直接在方法前加上static关键字。  

      静态属性的写法:

    class Foo{}
    Foo.a = 1;
    console.log(Foo.a);

    四,继承

      使用extends关键字进行继承。 

      只要一个表达式能够返回一个具有[[Construct]]属性以及原型的函数,就可以对其使用extends。

    function Animal(name){ this.name = name;}
    Animal.prototype.getName = function(){ console.log(this.name)};
    
    class Sheep extends Animal{
        constructor(name) {
             super(name)
        }
    }
    let sheep = new Sheep('yz');  
    sheep.getName();

       上面的Animal是es5的构造器,但也满足上面的要求,因此可以直接使用extends被继承。

        由于extends后可以接受任意的表达式,那么自然而然也可以创建混入:

    const Mixin1 = {
        getName(){ console.log(this.name)}
    }
    
    const Mixin2 = {
        addName() { console.log(this.name + this.age)}
    }
    
    function mixin (...mixinObj){
        let base = function () {};
        Object.assigin(base.prototype, ...mixinObj);
        return base;  
    }
    
    class MinxinAll extends mixin(Mixin1, Mixin2){
    constructor(name, age){
    super();
    this.name = name; this.age = age;
    }
    }

      这样所有MinxinAll的实例都可以使用 混入对象的方法。  若多个混入的对象有相同的属性, 则只有最后被添加的属性会被保留。

      使用extends的子类, 也可以继承父类的静态成员。

    五,super

      super只能在子类中使用,如果在没有extends的类中使用会报错。

      在构造器中,必须在访问this之前调用super();因为super是用来初始化this的。

      子类中可以使用super.方法()来访问原型的方法。

      当然,箭头函数无super。

      由于super是用来生成this的, 如果你只是想继承原型,而对父类的构造器没兴趣, 可以在constructor中不使用super,返回一个对象即可。

    class A {
        getOne() { return 1;}
    }
    class B extends A {
        constructor() {
            return Object.create(new.target.prototype);
        }
        getTwo() { return 2;}
    }
    
    let n = new B();
    n.getOne();
    n.getTwo();

      

    六,继承内置对象与Symbol.species属性

      继承内置对象的 子类, 调用内置对象的方法,返回的结果是子类的实例。

      比如:

    class MyArray extends Array{}
    
    let arr = new MyArray(1,2,3,4,5);
    let newArr = arr.slice(1, 4);
    // 按理来说 调用了slice之后,生成的应该是数组,结果返回的newArr却是 MyArray的实例

      Symbol.species 知名符号被用于 定义一个能返回函数的静态访问器属性。一般默认拥有Symbol.species属性的类型默认返回的都是this,即自身的构造器。

      子类继承的时候,可以重写 Symbol.species属性来指定生成的实例属于何种类型。

    七, new.target

      在简单的情况下, new.target就等于本类的构造函数。  这样的话,可以通过使用new.target来创建一个抽象基类。  即只能被继承,自身不能实例化的类。

      

    class Animal {
        constructor() {
             if (new.target === 'Animal') {
                 throw new Error('此类不能被实例化')
            }
        }
    }
    
    class Row extends Animal{
        constructor(name) {
            super();
            this.name = name;
        }
    }
    
    let r = new Row('yz');   // 正常
    
    let  a = new Animal();  // 抛出错误。

      

     

      

      

  • 相关阅读:
    省选模拟27
    省选模拟26
    省选模拟25
    省选模拟23
    PHP 各个框架的优缺点(超详细)
    windows 下安装中文版Git
    支付宝APP支付里设置应用网关和授权回调地址是不必填的
    linux服务器下安装phpstudy 如何命令行进入mysql
    js金钱转大写
    多个 (li) 标签如何获取获取选中的里面的某个特定值??
  • 原文地址:https://www.cnblogs.com/wjyz/p/10845094.html
Copyright © 2011-2022 走看看