xiaokeqi / i-learned

1 stars 0 forks source link

关于super的一道this指向题 #44

Open xiaokeqi opened 4 years ago

xiaokeqi commented 4 years ago

why这段代码输出如下?

class Polygon {
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }
  sayName() {
    console.log('Hi, I am a ', this.name + '.');
  }
}
class Square extends Polygon {
  constructor(width,height) {
    super(height, width);
    this.name = 'Square';
  }
  test() {
    //console.log(super);
    console.log(super.sayName(), '  test');
  }

}

var fn = new Square(1,2)
fn.test()

输出结果为:

Hi, I am a  Square.
undefined "  test"

这道题让我迷惑的点如下:

在es5中,

var obj = {
  name: 'xiaokeqi',
  foo: function(){
     console.log(this.name);
  }
}
obj.foo() // xiaokeqi

而上段代码中,super.sayName()中的this.name 不是应该是Polygon类的name吗?而结果却是

Square

why?why?why?

原因是es6中class和extends均是语法糖

extends通过prototype来实现原型链属性的继承

而构造函数中super(),则是通过Parent.call(this,args1,args2)来实现,在上个例子中,construtor中 super(height,width),是通过Polygon.call(this,height,width),this指Square

而test中的super.sayName(),则是通过Polygon.prototype.sayName.call(this),this指Square来实现。

class Rectangle {
  constructor() {
  }
  static logNbSides() {
    return 'I have 4 sides';
  }
  logNbSides() {
    return 'I have 5 sides';
  }
}

class Squares extends Rectangle {
  constructor() {
        super();
  }
  logDescription() {
    return super.logNbSides() + ' which are all equal';
  }
  static logDescription() {
    return super.logNbSides() + ' which are all equal';
  }
}
console.log(new Squares().logDescription()); // 'I have 5 sides which are all equal'
console.log(Squares.logDescription());// 'I have 4 sides which are all equal'

这段代码中,静态函数的继承,则是通过

    Object.setPrototypeOf ? Object.setPrototypeOf(Squares, Rectangle) : Squares.__proto__ = Rectangle; 

实现