Skip to content

JS中的继承专题(ES6) #27

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

Open
Reaper622 opened this issue Dec 4, 2019 · 0 comments
Open

JS中的继承专题(ES6) #27

Reaper622 opened this issue Dec 4, 2019 · 0 comments
Labels

Comments

@Reaper622
Copy link
Member

Class 的定义

ES6中的class本质还是函数,即类的数据类型还是函数,类本身指向构造函数。

class Person {
    //...
}

typeof Person // 'function'
Person === Person.prototype.constructor // true
// 另一种定义class的方式是表达式形式
const ThePerson = class {
    //...
}

注意class本身不具有变量提升,并存在暂时性死区

const reaper = new Person('reaper'); // ReferenceError: Cannot access 'Person' before initialization
class Person {
    constructor(name) {
        this.name = name;
    }
}

并且,class内默认开启严格模式,class内的所有方法,包括静态方法和实例方法,都是不可枚举的。「enumerable: false」

// 引用一个未声明的变量
function Bar() {
  this.bar = 42;
}
Bar.answer = function() {
  return 42;
};
Bar.prototype.print = function() {
  console.log(this.bar);
};
const barKeys = Object.keys(Bar); // ['answer']
const barProtoKeys = Object.keys(Bar.prototype); // ['print']

class Foo {
  constructor() {
    this.foo = 42;
  }
  static answer() {
    return 42;
  }
  print() {
    console.log(this.foo);
  }
}
const fooKeys = Object.keys(Foo); // []
const fooProtoKeys = Object.keys(Foo.prototype); // []

ES5中,构造函数可以不通过new执行,从而会给全局对象添加上属性,在ES6的class中,必须通过new调用,否则无法执行。

继承

在ES5中,我们通过子类寻找父类的方式是

function Super() {}
function Sub() {}

Sub.prototype = new Super();
Sub.prototype.constructor = Sub;
Sub.__proto__ === Function.prototype // true

与ES5不同的是,ES6的继承子类可以直接通过__proto__找到父类。

class Super {}
class Sub extends Super {}
// 表示构造函数的继承,总是指向父类
Sub.__proto__ === Super; // true
// 表示方法的继承,总是指向父类的原型
Sub.prototype.__proto__ === Super.prototype; // true

底层原因是babel在解析上面的代码时会解析为:

Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
Sub.__proto__ = Super

this

类方法的内部如果含有this,他就默认指向类的实例,但是不可单独使用类内的方法,否则会产生this指向错误。

一种方法时在构造方法中绑定this,这样就不会产生this指向错误。【React类组件内部】

class Person {
    constructor(name) {
        this.name = name;
        this.hello = this.hello.bind(this);
    }
    hello() {
        return this.name;
    }
}
let man = new Person('reaper');
let foo = man.hello
foo() // 'reaper'

super

我们在类的继承中,在子类的构造函数中需要使用到super()来执行父类的构造函数。

class Super() {
    constructor(name) {
        this.name = name;
    }  
}
class Sub() {
    constructor(name, age) {
        super(name); // 使用super
        this.age = age;
    }
}

如果不使用super,那么构建实例时会报错,这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。

在ES5的继承中,继承的实质是先创建子类的实例对象this,之后向子类的实例对象this上添加父类的方法Parent.call(this),而ES6的继承则是先创建父类的实例对象,然后调用子类的构造函数进行对this的修改,因此需要先调用super

@Reaper622 Reaper622 added the JS label Dec 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant