super关键字:
我们知道this关键字总是指向函数所在的当前对象,ES6又新增了另一个类似的关键字super,super关键字既可以当对象来用,也可以当函数使用。。。
第一种情况:
super作为函数来使用,代表父类的构造函数。ES6要求,子类的构造函数必须先先先(重要的事情写三遍)执行一次super函数。
class Father{
constructor(){
console.log("1");
}
}
class Son extends Father{
constructor(){
super()
}
}
上边代码中,子类Son的构造函数之中的super(),代表调用父类的构造函数。这是必须的,否则js引擎会报错。
注意,super虽然代表父类Father的构造函数,但是返回的是子类Son的实例,即super内部的this指的是Son的实例,因此super()在这里相当于Father.proptotype.constructor.call ( this )也就是让子类的调用父类里边的方法
class A{
constructor(){
console.log(new.target.name)
}
}
class B extends A{
constructor(){
super()
}
}
new A()//A
new B() // B
上边代码,B继承A,在super()执行的时候,指向了B类,而不是父类A,也就是说里边的this指向B。。。ES6规定,在子类普通方法中通过super调用父类的方法,方法内部的this指向当前的子类实例。。。
为了加深印象,我们在看一个例子:
class A{
constructor(){
this.name = "lxc"
}
showName(){
return this.name
}
}
class B extends A{
constructor(){
super()
this.name = "hahah"//这里要注意顺序,先调用super(),在写属性,写的时候找了半天bug
}
fn(){
console.log(super.showName())//hahah
}
}
new B().fn()
当super作为函数时,super()只能在子类的构造函数中,用在其他地方就会报错。。。
class A{
constructor(){
console.log(new.target.name)
}
}
class B extends A{
c(){
super()
}
}
new B() // 报错:'super' keyword unexpected here
上边代码,super()用在了c方法中,报错!!!
第二种情况:
super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
先看下在普通方法中:
var obj = {
name:"xiaochen",
say(){
return super.name
}
}
obj.__proto__.name = "lxc"
console.log(obj.say())//"lxc"
上边代码,我们手动在对象obj的原型上边(obj.__proto__指向Object构造函数的原型)添加属性name,调用say方法,会把原型上边的name属性值打印出来。。。当然obj.__proto__这种做法是不推荐的!!!
注意:super关键字,表示原型对象时,只能用在对象的方法之中,用在其他地方会报错。。。目前,只有对象的简写法可以让js引擎确认,是定义在对象的方法里。。。
class A{
constructor(){
}
p(param){
return param
}
}
class B extends A{
constructor(){
super()
console.log(super.p("lxc"))
}
}
new B() //lxc
上边代码,B类当中的super.p(),就是将super作为对象使用,这时super在普通方法里边,指向A.prototype,所以super.p()相等于A.prototype.p()。
这里要注意的是,super作为对象指向的是父级的原型,父级实例上边的方法或者属性是无法通过super调用的:
class A{
constructor(){
this.name = "lxc"
}
}
class B extends A{
constructor(){
super()
console.log(super.name)//undefined
}
}
new B()
上边代码中,name是父类的实例里边的属性,super无法调用!!!