define

In JS, we can think of mixins as a way to extend collection capabilities. It is well suited for js object prototyping, and we can share functionality from more than one Mixin to improve code reusability and reduce duplication

implementation

function Car (model = null, color = ' ') {
    this.model = model
    this.color = color    
}

function CarMove () {}

CarMove.prototype.run = function () {
    console.log('car is running')
}

CarMove.prototype.stop = function () {
    console.log('car has stoped')}Copy the code

In the above code, we put the Car property and the Car method into the two constructors, which is not recommended in real development, but just to show how Mixin patterns can be used.

Now all you have to do is write the Mixin function, as shown in the following code

function mixin (origin, source, ... rest) {
    const restLen = rest.length
    if (restLen) {
        for (let i = 0; i < restLen; i++) {
            origin.prototype[rest[i]] = source.prototype[rest[i]]
        }
    } else {
        for (let method in source.prototype) {
            if (!Reflect.has(origin.prototype, method)) {
                origin.prototype[method] = source.prototype[method]
            }
        }
    }
}
Copy the code

The Mixin function is responsible for mixing methods from the source object into the Origin object. You may want to use object. assign, but this function differs from object. assign in two ways.

The first is that the function can specify which attributes need to be mixed into the source object, as shown in the first judgment statement. If the call is called with three or more parameters, indicating that the attribute name is specified, only the specified attribute is mixed in and the rest is not processed.

The second point is priorities. In object. assign, if both the source Object and the target Object have an attribute, the attribute in the source Object overwrites the attribute in the target Object, as follows

const person1 = {
    name: 'foo'.gender: 'male'
}

const person2 = {
    name: 'bar'.age: 18
}

Object.assign(person1, person2)

console.log(person1)
Copy the code

The output of the above code is shown below

As you can see, the name attribute of person2 overrides the name attribute of person1, while the source object attribute takes precedence in the mixin function we wrote, as evidenced by the second if statement in the function.

Test mixin functions

mixin(Car, CarMove)

console.log(Car.prototype)
Copy the code

The output

Specify the attribute name

mixin(Car, CarMove, 'run')

console.log(Car.prototype)
Copy the code

The output

You can see that the mixin function is working fine

conclusion

Mixin patterns help improve function reuse and reduce system code duplication. When a program shares properties and behavior across objects, we can consider the Mixin pattern. However, the Mixin pattern also has its drawbacks. Some people believe that injecting functionality into object prototypes can lead to problems such as prototype contamination and uncertainty about function origin, so you need to weigh the pros and cons to make a choice.