리액트에서 상속 or 합성을 하면 js prototype 구조는 어떻게 될까?

바벨을 이용해 리액트 코드를 컴파일 해보고 싶었으나... 이번주 유독 야근 많아서 ES6의 클래스를 ES5에서 어떻게 표현하는 지 정도만 알아본다.

ES6 class

class Human {
  name;

  constructor(name) {
    this.name = name;
  }

  isValidName() {
    return this.name !== null && this.name !== undefined;
  }
}

const human = new Human('human');
console.log(human.name); // human
console.log(human.isValidName()); // true

const notHuman = new Human();
console.log(notHuman.name); // undefined
console.log(isValidName()); // false

ES5 prototype

function Human(name) {
  this.name = name;
}

Human.prototype.isValidName = function() {
  return this.name !== null && this.name !== undefined;
}

const human = new Human('human');
console.log(human.name); // human
console.log(human.isValidName()); // true

const notHuman = new Human();
console.log(notHuman.name); // undefined
console.log(isValidName()); // false

그렇다면... 상속은 어떻게 표현해야 할까?

class Human {
  name;

  constructor(name) {
    this.name = name;
  }

  isValidName() {
    return this.name !== null && this.name !== undefined;
  }

  hello() {
    console.log('hello', this.name);
  }
}

class Developer extends Human {
  skill;
 
  constructor(name, skill) {
    super(name);
    this.skill = skill;
  }

  skillChange(skill) {
    this.skill = skill;
  }

  hello() {
    console.log('hello', this.name, this.skill);
  }
}
function Human(name) {
  this.name = name;
}

Human.prototype.isValidName = function() {
  return this.name !== null && this.name !== undefined;
}

Human.prototype.hello = function() {
  console.log('hello', this.name);
}

function Developer(name, skill) {
  this.skill = skill;
  Human.call(this, name);
}

Developer.prototype = Object.create(Human.prototype);
Developer.prototype.constructor = Developer;
Developer.prototype.changeSkill = function(skill) {
    this.skill = skill;
};
Developer.prototype.hello = function() {
    console.log('hello', this.name, this.skill);
};

리액트의 class 또는 ES6의 class는 실제 JS에서 어떻게 존재하는가?

상속 or 합성을 했을 경우 scope는 어떻게 되는가?