javascript设计模式——混入模式

2026-04-16 03:24:39 225
分类:javascript归档

为什么要有混入模式(Mixin)

在继承或者实例化时,JS的对象机智并不会自动执行复制行为。简单地说,JS中只有对象,并不存在可以被实例化的类。由于在其他语言中类表现出来的都是复制行为,因此JS的开发者们想出一种模拟类的行为,这个方法就是混入。

定义

Mixin是掺合,混合,糅合的意思,就是将一个对象的一个或多个(或全部)属性(或方法)复制到另外一个对象,Mixin有的是对对象的操作,有的是对类的操作。

注意这个继承还是有区别的。js是一种只支持单继承的语言,毕竟一个对象只有一个原型,如果想实现多继承,那就简单暴力的把需要继承的父类的所有属性都拷贝到子类上,就是使用mixin啦。

特点

Mixin模式可以实现多重继承,可以把Mixin对象当做一个个零件仓库,可以直接把零件仓库里的零件给现有对象装上,能够方便地复用代码、增强现有对象。

对象合并

下面是一个简单的对象递归合并覆盖。

/**
 * 对象递归合并覆盖(相比比$.extend()未实现多参数)
 * @param {*} target 目标对象
 * @param {*] source 拷贝对象 
 * @param {boolean} overlay 是否覆盖
 * @returns {*} target
 */
function assign(target, source, overlay) {
    for (let key in target) {
        if (typeof target[key] === 'object' && overlay) {
            source[key] = apiUtil.assign(target[key], source[key], overlay);
        }
    }
    Object.assign(target, source);//Object.assign()未多级合并,所以使用递归实现  
    return target;
},

示例

var obj1 = {
    a: 1,
    b: {
        b1: 1,
        b2: 2
    },
    c: 3
}
var obj2 = {
    a: 'a',
    b: {
        b2: 'b2',
        b3: 'b3'
    }
}
assign(obj1, obj2, true);
console.log(obj1)

对象的方法复制

比如先创建一个包含各种通用方法的类,然后让其它类扩充于它。这个包含通用方法的类就叫掺元类。多数时候它不会直接实例化或调用,而是作为其它类的模板用于扩充。

/**
 * 混入模式
 * @param {*} target 目标对象
 * @param {*] source 拷贝对象
 * @param {boolean} overlay 是否覆盖
 * @returns target
 */
function mimix(target,source,overlay) {
    target = 'prototype' in target ? target.prototype : target;
    source = 'prototype' in source ? source.prototype : source;
    for (var key in source) {
        if (source.hasOwnProperty(key) && (overlay ? source[key] != null : target[key] == null)) {
            target[key] = source[key];
        }
    }
    return target;
}

示例

function Tool1() {
    this.name = '工具1';
}

Tool1.prototype.fun1 = function () {
    console.log('使用工具1');
};

function Tool2() {
    this.name = '工具2';
}

Tool2.prototype.fun2 = function () {
    console.log('使用工具2');
};

function Tool() {
    this.name='工具';
};
Tool.prototype.execute = function () {
    console.log('使用工具');
};

augment(Tool,Tool1,true);
augment(Tool,Tool2,true);
var tool=new Tool();
console.log(tool);

总结

Mixin是JavaScript中用的最普遍的模式,几乎所有流行类库都会有Mixin的实现,只是叫法不一样,比如 jQuery的extend,可以浅拷贝和深拷贝。

缺点

Mixin是一种很灵活的代码复用方式,但把功能注入原型对象会导致原型污染和函数来源方面的不确定性,在大型系统中可能是一个严重的问题。可以通过详细的文档来解决函数来源不确定的问题,但原型污染是不可避免的。

参考: