es6中class使用详解

class基本语法

   function Parent(job){
       this.job = job
   }
   Parent.prototype.showJob = function(){
       alert(this.job);
   }
   var p = new Parent('teacher');

通过class关键字的语法糖,es6的写法为

   class Parent {
       constructor(job){
           this.job = job;
       }
       showJob(){
           alert(this.job)
       }
       fn1(){ }
       fn2(){ }
       ...
   }

constructor方法对应我们原来的构造函数,而showJob方法直接定义在了Parent构造函数的原型上,注意:这里的定义不需要加上function关键字,方法之间也不需要逗号(加上逗号会报错)。那么我们对es6的写法进行测试

   typeof Parent   // 'function'
   Parent === Parent.prototype.constructor

与es5构造函数的行为基本一致,但是有一个隐藏的比较大的区别:

   function Parent1(){ this.job = 'teacher' }
   class Parent2(){
      constructor(){
          this.job = 'teacher';
      }
   }
   Parent1()  // undefined
   Parent2()  // 报错,只能通过new关键字来调用

而且,class不存在覆盖声明

   class Parent {
   }
   ...
   class Parent{
   }
   //覆盖声明这个类会报错

不存在变量提升

   var p = new Parent();    // 报错
   class Parent{
   }

在class中定义的方法不可枚举

   Object.keys(Parent.prototype)  // []
   //这时候我们通过es5语法添加一个原形上的方法
   Parent.prototype.toString = function(){ }
   Object.keys(Parent.prototype)   // ["toString"]

这虽然有点尴尬,但实际开发中我们一般不会需要去枚举原形上的方法
我们可以在class中使用Object.assign(ie不支持)来一次性添加许多方法

   class Parent(){
       ...
       Object.assign(Parent.prototype,{
           showJob(){ },
           toString(){ }
       })
   }

constructor方法

constructor方法的返回值是实例对象(this),可以指定返回另一个对象

   class Parent {
      constructor(){
          return { }
      }
   }
   var p = new Parent();
   p instanceof Parent   // false

当然确实没必要在constructor中返回其他对象,如果不写constructor,默认只返回一个实例对象,只是对象上的属性没有在构造中定义而已。
在继承中,constructor一定要写上super()

   class Parent {
       constructor(){
           this.job = 'teacher'
       }
   }
   class Child extends Parent{
       constructor(){
           super();
       }
   }
   var child = new Child()
   child.job  // 'teacher'

私有方法

es6的class还是没有提供私有方法的接口,只能曲线救国,将方法移出构造函数,使用call来调用

   class Parent{
      constructor(){
         this.job = 'teacher';
      }
      showJob(){
          _showJob.call(this);
      }
   }
   function _showJob(){
       alert(this.job);
   }

静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”

   class Parent {
      constructor(){
         this.job = 'teacher';
      }
      static showJob() {
         alert(this.job);
      }
      static showOther() {
         alert('hello');
      }
   }
   Parent.showJob();  // 'hello'
   Parent.showJob();   // undefined,静态方法无法读取实例上属性

父类的静态方法,可以被子类继承

   class Parent {
      static showOther() {
         alert('hello');
      }
   }
   class Child extends Parent {
       constructor() {
          super();
       }
   }
   Child.showOther();   // 'hello'

this的指向

类的方法中如果含有this关键字(调用了类属性或者类方法),单独使用类的方法,有可能报错

   class Parent{
       constructor(){
           this.job = 'teacher';
       }
       toShowJob(){
           this.showJob();
       }
       showJob(){
           alert(this.job)
       }
   }
   var p = new Parent()
   p.toShowJob()   // alert('teacher')
   //然而下面的写法会报错
   const a = new Parent();
   const { toShowJob } = a;
   toShowJob()  // 报错

一种解决方法是

   class Parent{
       constructor(){
          //注意,绑定的是toShowJob方法
          this.toShowJob = this.toShowJob.bind(this);
       }
   }

另一种方法是使用箭头函数,箭头函数会默默地绑定this

   class Parent{
       constructor(){
           this.toShowJob =()=>{
               this.showJob();
           }
       }
   }

当然也可以考虑在new的时候const a = selfish(new Parent())再加一个中间函数selfish

你可能感兴趣的:(Es6)