Skip to content
New issue

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

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

Already on GitHub? # 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
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

1 participant