当前位置:网站首页>Using Es5 to realize the class of ES6

Using Es5 to realize the class of ES6

2020-11-06 01:16:02 Front end development blog

ES5 Parasitic combinatorial inheritance of

function parent (age) {
    this.age = age
}

parent.prototype.say = function () {
    console.log(this.age)
}

function sub (age, value) {
    parent.call(this, age)
    this.value = value
}

sub.prototype = Object.create(parent.prototype, {
    constructor: {
        value: sub,
        enumerable: false,
        writable: true,
        configurable: true
    }
})

ES6 Of Class

About Class See here :es6.ruanyifeng.com/#docs/class

ES6 Of class Can be seen as just a grammar sugar , Most of its functions ,ES5 Can do it , new class The writing method is just to make the writing method of the object prototype clearer 、 It's more like the syntax of object-oriented programming . But they are different .

difference :

  • Class must use new call , Otherwise, an error will be reported .ES Can be used as a normal function
  • All defined methods inside the class , It's all inestimable .( Including internally defined static methods )
  • Class static methods can also be inherited by subclasses
  • Can inherit native constructors

    • ES5 It is to create an instance object of subclass first this, Then add the attribute of the parent class to the subclass , The internal properties of the parent class cannot be obtained , The result is that the native constructor cannot be inherited .
    • ES6 Allow inheritance of native constructors to define subclasses , because ES6 It is to create an instance object of the parent class first this, And then we decorate it with subclass constructors this, Make all behaviors of the parent class inheritable

Use ES5 Simulation Implementation ES6 Of class

According to the above differences , We look at it step by step .

1. new Operator check function

solve the problem :

  • Class must use new call , Otherwise, an error will be reported .ES Can be used as a normal function
function _checkType (obj, constructor) {
    if (!(obj instanceof constructor)) {
        throw new TypeError('Cannot call a class as a function')
    }
}

2. Internal methods cannot be enumerated

solve the problem :

  • All defined methods inside the class , It's all inestimable .( Including internally defined static methods )
//  Modify the constructor descriptor 
function defineProperties (target, descriptors) {
    for (let descriptor of descriptors) {
        descriptor.enumerable = descriptor.enumerable || false

        descriptor.configurable = true
        if ('value' in descriptor) {
            descriptor.writable = true
        }

        Object.defineProperty(target, descriptor.key, descriptor)
    }
}

//  structure class
// constructor  Represents the corresponding class constructor object 
// protoDesc  Express class Internally defined methods 
// staticDesc  Express class Internally defined static methods 
function _createClass (constructor, protoDesc, staticDesc) {
    protoDesc && defineProperties(constructor.prototype, protoDesc)
    staticDesc && defineProperties(constructor, staticDesc)
    return constructor
}

3. Real creation class

const Foo = function () {
    function Foo(name) {
        _checkType(this, Foo) //  Check first if it's new Called 

        this.name = name
    }

    _createClass (Foo, [ //  It means that class Internally defined methods 
        {
            key: 'say',
            value: function () {
                console.log(this.name)
            }
        }
    ], [ //  It means that class Internally defined static methods 
        {
            key: 'say',
            value: function () {
                console.log('static say')
                console.log(this.name)
            }
        }
    ])

    return Foo
}()

Come here class Implementation complete , Check it out .

  • Call it directly first Foo(), The result is :

  • Use new The operator , Generate an object
const foo = new Foo('aaa')

  • Print out the methods defined on the prototype chain

so say Methods are not enumerable .

  • Print the static method

Visible static method say It can't be enumerated .

4. Implement prototype chain inheritance and static method inheritance , And think about inheriting null The situation of

solve the problem :

  • Class static methods can also be inherited by subclasses
function _inherits(subClass, superClass) {
    if (typeof superClass !== 'function' && superClass !== null) {
        throw new TypeError('Super expression must either be null or a function, not' + typeof superClass)
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
        }
    })

    if (superClass) {
        Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass
    }
}

5. Use the instance object of the parent class this

Problem solved :

  • Can inherit native constructors

    • ES5 It is to create an instance object of subclass first this, Then add the attribute of the parent class to the subclass , The internal properties of the parent class cannot be obtained , The result is that the native constructor cannot be inherited .
    • ES6 Allow inheritance of native constructors to define subclasses , because ES6 It is to create an instance object of the parent class first this, And then we decorate it with subclass constructors this, Make all behaviors of the parent class inheritable
//  Of the parent class this; if null, Then return to yourself 
function _possibleConstructorReturn(self, call) {
    if (!self) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called")
    }
    return call && (typeof call === 'object' || typeof call === 'function') ? call : self
}

6. Create subclass class

const Child = function (_Parent) {
    _inherits(Child, _Parent) //  Inherit the properties of the parent prototype and static methods 

    function Child(name, age) {
        _checkType(this, Child)

        //  First use the parent instance object this, Back again 
        const _this = _possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).call(this, name))
        _this.age = age
        return _this
    }
    return Child
}(Foo)

Subclass class Implementation complete . Check it out .

  • A print Child.say()

Child There is no static method defined in itself , But its parent class has a definition . Succeeding .

  • Construct a subclass that inherits the native constructor
const Child = function (_Parent) {
    _inherits(Child, _Parent)

    function Child(name, age) {
        _checkType(this, Child)

        const _this = _possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).call(this, name))
        _this.age = age
        return _this
    }
    return Child
}(Array)

const c = new Child('bbb', 12)

Succeeding .

Related articles

  1. ES2020 in Javascript 10 New features you should know about
  2. To relive ES6 Core concepts and basic usage
  3. JavaScript object : Do we really need to simulate classes ?
original text : https://juejin.im/post/684490...

Last , Welcome to my official account. : Front end development blog , Share new technical articles every day .

版权声明
本文为[Front end development blog]所创,转载请带上原文链接,感谢