Class

作者: zdxhxh | 来源:发表于2019-11-28 09:34 被阅读0次

    面向对象oop是业务编程的核心,精通oop等于精通世界万物,无所不能

    在JS中,生成实例的传统方法的通过构造函数

    而继承往往通过prototype这个对象实现

    class

    es6的class只是一个语法糖,它的继承模式由es5就可以做到

    新的class写法只是让对象原型的写法更加清晰

    class A { 
      constructor(x,y) { 
        this.x = x 
        this.y = y
      }
      toString() { 
        ...
      }
    }
    

    定义类方法的时候,前面不需要加上function这一个关键字,直接把函数定义放进去就行了

    与传统es5的方法一样,类方法函数在prototype上

    但要明白的是,class不支持安全模式,必须使用关键字new 创建对象

    class A {}
    const a = A() // logs TypeError: Class constructor A cannot be invoked without 'new'
    

    与es5不同的时,类的方法(包括构造函数)是不可枚举的,这意味着它不会在for in中出现

    class A { 
      toString() { 
        console.log('我想搞事情')
      }
    }
    console.log(Object.keys(A.prototype)) // logs []
    console.log(Object.getOwnPropertyNames(A.prototype)) // logs [ 'constructor', 'toString' ]
    
    B.prototype.toString = function() { 
      console.log('BBBBB')
    }
    console.log(Object.keys(B.prototype)) // logs [ 'toString' ]
    console.log(Object.getOwnPropertyNames(B.prototype)) // logs [ 'constructor', 'toString' ]
    

    constutor

    constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

    class A {} 
    // 等于
    class A {
      construtor() {}
    } 
    

    constructor方法默认返回实例对象(即this),当然,你也可以指定返回另外一个对象。

    实例

    注意 : 在浏览器环境中,浏览器厂商实现了proto的私有属性,该属性会指向实例的原型对象,但不建议在生产环境使用该属性,我们可以使用Object.getPrototypeOf方法获取实例对象的原型

    取值函数(getter)和存值函数(setter)

    在类的内部可以使用get和set关键字,对某个属性设置存值函数与取值函数 拦截该属性的存储行为

    class A { 
      constructor() { }
      get prop() {
        return 'getter'
      }
      set prop(value) {
        console.log('setter' + value)
      }
    }
    

    存值函数与取值函数是设置在属性的Descriptor对象上的

    var descriptor = Object.getOwnPropertyDescriptor(
      A.prototype, "prop"
    );
    
    "get" in descriptor  // true
    "set" in descriptor  // true
    

    属性表达式

    类的属性名,可以采用表达式

    class A { 
      constructor(length)
      ["fuckyou"]() { 
    
      }
    }
    

    上面的代码中,,Squrae类的方法名为getArea

    class表达式

    与函数一样,类也可以使用表达式的形式定义。

    const MyClass = class Me {
      getClassName() {
        return Me.name;
      }
    };
    

    根据这一特性,可以写出立即执行的Class

    let a = new class {
      constructor(name) {
        this.name = name;
      }
    
      sayName() {
        console.log(this.name);
      }
    }('张三');
    
    a.sayName(); // "张三"
    

    注意点

    • class默认严格模式
    • 暂时性死区,es5构造函数会存在提升现象,而es6不存在提升,这意味着在class定义前会出现暂时性死区
    • name,函数具有name属性,es6的class也一样
    • 静态方法,class内部用static声明的方法不会被继承,只能通过类名调用,这与java一样
    • class中,实例属性可以直接书写xxx = '',而不写在构造函数中,一般用于给实例赋予初始属性而使用

    new.target

    es6为new命令新增了一个target属性,返回new命令作用域的那个构造函数,如果构造函数没有使用new命令,则该属性为undefined,这优点类似安全模式

    我们可以使用这个命令代替安全模式的前置判断

    function A(xx) { 
      if(this instanceof A) {
        this.xx = xx 
      } else { 
        return new A(xx)
      }
    }
    
    function A(xx) { 
      if(new.target === A) { 
        this.xx = xx
      } else { 
        return new A(xx)
      }
    }
    

    当然,它的正确使用应该是写抽象类的时候

    class A{ 
      constructor() { 
        if(new.target ===  A) { 
          // 抛出错误 : 本类不能实例化
          return new TypeError('this is abstract class you must inhert and complete it') 
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:Class

          本文链接:https://www.haomeiwen.com/subject/vduvwctx.html