ES6之class基本语法

类这个概念对于作后台的应该是很是熟悉,JavaScript的类对于其余面向对象的语言差别很大,只能使用构造函数生成实例对象。为了接近传统语言,ES6引入了class类这个概念,经过class关键字定义类。编程

Class实际上是一个语法糖,几乎全部功能均可以用其余方法实现,只是让代码更清晰,更像面向对象编程。bash

语法:函数

class User{  

  constructor(){     

   console.log('默认调用');  

  }  

  eat(){    

    console.log('eat方法');  

  }

}
var user = new User();//默认调用

user.eat()//eat方法
复制代码

注意,类的方法是不能加function关键字,方法之间也不能用逗号分隔,否则会报错。类的全部方法都定义在类的prototype方法。在类的实例调用方法就是调用原型上的方法。ui

class User{  

  eat(){}

}
复制代码

等同于:this

function User() {}

User.prototype.eat = function () {}
复制代码

类内部定义的方法都是不可枚举的,这跟ES5不同。spa

Constructor方法:prototype

这个方法是默认方法,经过new生成实例对象的时候自动调用,每一个类都会有,若是没有显式定义,会自动添加一个空的constructor方法。默认返回实例对象,也就是this。你也能够返回另外的对象,这跟构造函数是同样的。类必须使用new调用,而咱们的构造函数还能当作方法直接调用。code

与 ES5 同样,实例的属性除非显式定义在其自己(即定义在this对象上),不然都是定义在原型上(即定义在class上),类的全部实例共享一个原型对象,所以一个实例对象经过原型__proto__改写了原型,全部实例对象都会改变,全部不推荐使用实例的__proto__改写原型。cdn

一样的,getter函数和setter函数也能够在类里面使用关键字get和set:对象

class User{  

  constructor(){    

    this.name = 'wade'; 

   }    get eat(){   

   return '这是get';  

  }  

  set eat(val){     

   console.log('set调用了');  

  }

}

var user = new User();

user.eat = 3//set调用了

console.log(user.eat);//这是get
复制代码

表达式:

属性能够用[]表达式,这个跟对象是同样的,类也能够直接用表达式定义:

var val = 'my'

var User = class Muser{   

 [val](){     

       }

}
复制代码

Muser只能在class内部可用,class外部使用User。若是内部不使用,也能够省略Muser或者当即执行class:

var User = class {}

var user = new class{}()
复制代码

要注意,class默认就是严格模式,并且不存在变量提高,name的属性也是返回class关键字后面的类名,还能够使用Gernerator方法。类方法内部的this默认指向类的实例,单独拿出来使用会报错。

类的方法前面加上static关键字,那么这个方法不会被实例继承,能够经过类调用,这个方法叫作静态方法:

class User{  

  static eat(){     

   console.log('eat');  

  }

}var user = new User();

console.log(user.eat());//报错

User.eat()//eat
复制代码

若是静态方法包含this关键字,这个this指的是类,而不是实例:

class User{  

  static eat() {    

    this.say();  

  }  

  static say() {    

    console.log('hello');  

  }  

  say() {     

   console.log('world');  

  }

}

User.eat() // hello
复制代码

静态方法和非静态方法还能够重名。静态方法是能够被子类继承的。

实例属性除了定义在constructor里面,还能直接定义在最顶层:

class User1{  

  constructor(){    

    this.name = 'wade';  

  }

}

class User2{  

  name = 'kobe';

}

console.log(new User1().name);//wade

console.log(new User2().name);//kobe
复制代码

Class自己的属性叫作class的静态属性,Class.propName,不是定义在实例对象this上的属性。Class内部只有静态方法没有静态属性,如今只有一种写法:

class User{};User.prop = 1;

可是有提案使用static定义:

class User{  

  static prop = 1;

};
复制代码

从代码组织原则和声明来看,这样的写法无疑是更好的。

咱们都知道代码封装私有属性和私有方法是很重要的,可是ES6的class暂时是没有提供的。变通的解决方法好比区分命名、方法移出模块、用symbol变量等。但都不是很好。如今有个提案,使用#来提供私有属性:

class User{  

  #prop = 1; 

  #eat(){}

};
复制代码

只能在内部使用,外部访问就报错。私有属性也能够设置 getter 和 setter 方法。私有属性不限于从this引用,只要是在类的内部,实例也能够引用私有属性:

class User{  

  #prop = 1; 

  static eat(user){     

   console.log(user.#prop); 

  }

};

User.eat(new User());//1
复制代码

new是从构造函数生成实例对象的命令。ES6 为new命令引入了一个new.target属性,该属性通常用在构造函数之中,返回new命令做用于的那个构造函数。若是构造函数不是经过new命令或Reflect.construct()调用的,new.target会返回undefined,所以这个属性能够用来肯定构造函数是怎么调用的:

function User() {  

  console.log(new.target === User);//true  

  console.log(new.target !== undefined);//true

}

var user = new User();
复制代码

若是不是new:

function User() {  

  console.log(new.target === User);//false  

  console.log(new.target !== undefined);//false

}

User();
复制代码

Class 内部调用new.target,返回当前 Class:

class User{  

  constructor(){    

    console.log(new.target === User)//true  

  }

}

new User();
复制代码

子类继承父类时,new.target会返回子类。利用这个特色,能够写出不能独立使用、必须继承后才能使用的类。

相关文章
相关标签/搜索