Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6 系列之 Class #79

Open
yangtao2o opened this issue Apr 6, 2020 · 0 comments
Open

ES6 系列之 Class #79

yangtao2o opened this issue Apr 6, 2020 · 0 comments

Comments

@yangtao2o
Copy link
Owner

yangtao2o commented Apr 6, 2020

ES6 系列之 Class

class

ES6 的 class 可以看作一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

class Person {
  // 类的内部所有定义的方法,都是不可枚举的
  constructor(name) {
    // 实例属性
    this.name = name;
  }

  // 实例方法
  sayHello() {
    return "hello, I am " + this.name;
  }

  // 静态属性
  static _name = "ming";

  // 静态方法
  static _getName() {
    return "my name is " + this._name;
  }

  // getter 和 setter
  get age() {
    return "20 years old";
  }
  set age(newAge) {
    console.log("new age 为:" + newAge);
  }
}
// 静态属性
// Person._name = "ming";

var me = new Person("tao");

me.age = 28;
// new age 为:28

console.log(me.age); // 20 years old
console.log(me.name); // tao
console.log(me._name); // undefined
console.log(me._getName()); // Uncaught TypeError: me.getName is not a function

console.log(Person._name); // ming
console.log(Person._getName()); // my name is ming

Person(); // Uncaught TypeError: Class constructor Person cannot be invoked without 'new'

转换成 ES5:

function Person(name) {
  // 实例属性
  this.name = name;
}

// 静态属性、方法
Person._name = "ming";
Person._getName = function() {
  return "my name " + this._name;
};

Person.prototype = {
  constructor: Person,
  // getter 和 setter
  get age() {
    return "20 years old";
  },
  set age(newAge) {
    console.log("new age 为:" + newAge);
  },
  // 实例方法
  sayHello() {
    return "hello, I am " + this.name;
  }
};

var me = new Person("tao");

me.age = 28;
// new age 为:28

console.log(me.age); // 20 years old
console.log(me.name); // tao
console.log(me._name); // undefined
// console.log(me._getName()); // Uncaught TypeError: me.getName is not a function

console.log(Person._name); // ming
console.log(Person._getName()); // my name is ming

Person(); // 无报错

Babel 编译结果:地址

ES6 extend

Class 通过 extends 关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

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

class Child extends Parent {
  constructor(name, age) {
    // super 关键字表示父类的构造函数,相当于 ES5 的 Parent.call(this)
    super(name);
    this.age = age;
  }
}

var child1 = new Child("kevin", "18");

console.log(child1);

对应 ES5 寄生组合式继承:

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

Parent.prototype.getName = function() {
  console.log(this.name);
};

function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child1 = new Child("kevin", "18");
console.log(child1);

子类的 proto

在 ES6 中,父类的静态方法,可以被子类继承。

这是因为 Class 作为构造函数的语法糖,同时有 prototype 属性和 __proto__ 属性,因此同时存在两条继承链。

  1. 子类的 __proto__ 属性,表示构造函数的继承,总是指向父类。
  2. 子类 prototype 属性的 __proto__属性,表示方法的继承,总是指向父类的 prototype 属性。
class Parent {}

class Child extends Parent {}

// 相比寄生组合式继承,ES6 的 class 多了一个 Object.setPrototypeOf(Child, Parent) 的步骤。
console.log(Child.__proto__ === Parent); // true
console.log(Child.prototype.__proto__ === Parent.prototype); // true

原文链接:

@yangtao2o yangtao2o pinned this issue Apr 8, 2020
@yangtao2o yangtao2o unpinned this issue Apr 8, 2020
@yangtao2o yangtao2o changed the title ES6 系列之 Babel 是如何编译 Class 的 ES6 系列之 Class Apr 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant