温故而知新:JavaScript中的类

57 阅读2分钟

ES5中构造函数

在ES5中没有类的概念,但是我们可以通过构造函数来实现类

function Parent(name, sex) {
    this.name = name
    // 实例属性
    this.sex = sex
    // 实例方法
    this.run = function() {
        console.log('runing')
    }
}
// 静态属性
Parent.prop = 'hello'
// 静态方法
Parent.classMethod = function() {
    console.log('我是静态方法')
}
// 原型方法
Parent.prototype.speek = function() {
    console.log('speeking')
}
const parent = new Person('tony', '男')

ES6中Class

ES6中的Class可以看作是一个语法糖(底层还是通过构造函数去创建的),它的绝大部分功能,ES5都可以实现,新的Class的写法只是让对象原型的写法更加清晰,更像面向对象编程的写法。

class Parent {
    // 静态属性,不能被实例对象继承,只能通过class直接调用
    static staticProp = 'hello world'
    constructor(name, sex) {
        this.name = name
        // 实例属性
        this.sex = sex
        // 实例方法
        this.run = function() {
            console.log('runing')
        }
    }
    // 静态方法,不会被实例继承,但可以被子类继承
    static classMethod() {
        console.log('我是静态方法')
    }
    // 原型方法,会被实例继承
    speek() {
        console.log('speek')
    }
    // 原型方法
    sleep() {
        return 'sleeping'
    }
}

// 子类Sun继承父类Parent
class Sun extend Parent {
    constructor(name, sex, age) {
        // 通过super调用父类的constructor函数,将父类的实例对象和属性添加到子类的this上,实现继承
        // 子类自己的this对象,必须先通过调用父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后对其进行加工,加上自己的实例属性和方法,如果不调用super方法,子类就得不到this对象
        super(name, sex)
        this.age = age
    }
    sleep() {
       return this.name + super.sleep() // 调用父类原型对象的sleep()
    }
}

const parent = new Parent('tony', '男')
const sun = new Sun('tim', '男', '10')
  • class中constructor是内部默认的方法,如果没有声明则会被默认添加和调用,通过new关键字操作实际是调用constructor方法, 返回实例对象(即this)

  • class中内部可以通过static关键字定义静态属性和方法,直接通过类来调用,实例对象不能调用

  • 子类的this对象是通过super()调用父类的constructor构造函数来实现的, 在调用super之前不能使用this进行赋值操作,赋值会报错

super调用

super作为函数调用

子类B的构造函数中的super,指向父类的构造函数constructor

class A {}
class B extend A {
    constructor() {
        super()
    }
}

要注意的是:super虽然代表了父类的构造函数,但是返回的是子类B的实例,即super内部的this指的是B的实例

super作为对象调用

在普通方法中:指向父类的原型对象

在静态方法中:指向父类

两者区别

  • ES5声明的构造函数有变量提升,ES6声明的class类没有提升(这种规定的原因与继承有关,必须保证子类在父类之后定义)

  • ES5中通过prototype原型添加的方法是可以被枚举的,而ES6中在class内部添加的原型方法是不可被枚举的