在写类以前,咱们先看看一个概念——语法糖,刚开始听到这个词时,是在我面试时,当时面试官问我es6中的语法糖有哪些。毫无疑问,我答不上来,由于我连语法糖是什么都不知道,那么如今我就从什么是语法糖开始来进行展开吧!
语法糖(syntactic sugar)是指编程语言中能够更容易的表达一个操做的语法,它可使程序员更加容易去使用这门语言,操做能够变得更加清晰、方便,或者更加符合程序员的编程习惯。用比较通俗易懂的方式去理解就是,在以前的某个语法的基础上改变了一种写法,实现的功能相同,可是写法不一样了,主要是为了让开发人员在使用过程当中更方便易懂。程序员
这个话题其实很大,es6中的语法糖太多了,例如经常使用的箭头函数,解构赋值等都是语法糖,具体的能够看看这篇文章,讲得很仔细,在这里给博主👏。es6
接下来就进入正题了,揭开es6中class的神秘面纱。首先为何会有class的概念,在es5时期,生成实例是经过构造函数,可是若是要添加方法的话,就必须在原型上去添加,这样构造函数new出来的实例才能够用这个方法。就好比这样:面试
// Person为构造函数 function Person (name, age) { this.name = name, this.age = age } // 在构造函数的原型上添加方法 Person.prototype.getName = function () { return this.name } // 构造一个实例 var huhaha = new Person('huhaha', 21) // 在实例上调用该方法 var myName = huhaha.getName() console.log(myname) // huhaha
那么在es6中怎么使用class去实现它呢,先看代码再解释~编程
// 类中的this指向建立的实例 class Person { constructor (name, age) { this.name = name this.age = age } getName () { return this.name } } // 构造一个实例 let huhaha = new Person('huhaha', 21) // 在实例上调用该方法 const myName = huhaha.getName() console.log(myname) // huhaha
咱们能够看到经过es6去实现,更容易理解,而且代码量也有所减小。使用这种方式,咱们能够清楚的明白,前面使用了class的就是一个类,那么它就有构造实例的能力,而且constructor中放的是每一个经过该类构造出来的实例均可以得到属性,在constructor外面放的是能够得到的方法。
除了在写法上的区别,class和构造函数还有一个区别就是在class中定义的方法是不可枚举的,而在es5中原型上添加的方法是可枚举的。还有一点就是,使用class,在建立实例的时候必须使用new,而普通的构造函数是能够省略的。segmentfault
constructor是类的默认方法,若是在写class时,没有添加该方法,js引擎会默认添加这个方法。经过new去构造实例时,会自动去调用该方法,该方法默认返回的是该实例对象,可是也能够指定返回的对象,好比下面的状况:编程语言
class Fun { constructor () { // 改变默认返回的内容 return Object.create(null) } } let fun = new Fun() // fun不是Fun的实例 fun instanceof Fun // false
若是在类中一个属性的前面有static关键词时,就代表这个属性是静态属性。静态属性是类的属性,经过类构造的实例中是没有这个属性的,只有经过类才能够拿到这个属性。函数
若是在类中一个方法的前面有static关键词时,就代表这个方法就是静态方法。静态方法的特殊性有两点:首先,在由该类建立的实例中,是不能调用该方法的,这个方法只能经过类自己去调用;其次,若是在该方法中包含this,那么this指向的是该类,下面的例子能够证实这两点:this
class Person { constructor (name, age) { this.name = name this.age = age } getName () { return this.name } static age = 42 static getAge () { return this.age } } let huhaha = new Person ('huhaha', 21) huhaha.getName() // huhaha huhaha.getAge() // TypeError: huhaha.getAge is not a function Person.getAge() // 42
咱们知道在es5中继承的方式有不少种,最简单的方式就是经过原型链进行继承,可是就算是这种最简单的方式也会让人很容易混乱;为了解决这个问题,es6中使用extends关键字去表示继承,并在子类中使用super关键字去继承父类的内容,下面这个例子能够很好的代表es6中的继承关系:es5
// Father为父类 class Father { constructor (x, y) { this.x = x this.y = y } toString () { return 'string' } } // Child为子类,继承Father class Child extends Father { constructor (x, y, z) { super (x, y) // 调用Father类中的constructor(x, y) this.z = z } toString () { return super.x + super.toString() // 经过super调用Father类中定义的方法 } }
在上面的例子中,咱们能够看到,子类继承父类最关键的地方就是,须要在子类的constructor中使用super去继承父类,它在这里表示的是父类的构造函数,用来新建父类的this对象。这里完成继承的思想是,子类是经过先在父类中建立一个实例,拥有了父类中定义的属性和方法,而后子类再添加本身的属性和方法。这个和es5中的思想不太一致的地方在于es5中是先建立子类的this对象,而后将父类的属性和方法添加到子类的this中。经过图来简单的解释就是:spa
以前咱们有讲到类的静态属性和静态方法,当时说的是前面使用了static关键字的就是指这个类上面属性和方法,实例是拿不到的。在这里咱们能够看做是这个静态的内容,只是针对于建立实例,对于子类的继承是不影响的,也就是说在子类中是能够继承到父类中的静态属性和方法的,甚至于咱们能够在子类中对这些属性和方法进行覆盖。
咱们能够经过Object.getPrototypeOf方法去检测子类与父类之间的继承关系,以下例:
// 检测Father是否为Child的父类 Object.getPrototypeOf(Child) === Father // true
super关键字是实现继承最关键的内容,它有两个身份,第一个是看成函数使用,第二个是看成对象使用,这个点其实在上面的例子也有体现到,如今咱们再来仔细说一说。
看成为函数使用时,super表示的是父类的构造函数,咱们须要注意如下几点:
看成为对象去使用的时候,通常就是经过super去调用父类的属性和方法了,可是这里须要注意的是,使用super只能获取到父类原型中包含的属性和方法,也就是说后面经过实例添加的属性和方法是获取不到的。咱们须要注意如下几点:
因为时间不是很够,后面两块内容下次再补充