Mixin是JavaScript中用的最普遍的模式,可以就任意一个对象的全部或部分属性拷贝到另一个对象上。从提供的接口来看,有的是对对象的操作,有的是对类的操作。对类的操作又称为掺元类(Mixin classes)几乎所有流行类库都会有Mixin的实现。

比如说:

   jQuery的$.extend 操作对象,将其它对象的属性方法拷贝到目标对象。

  RequireJS的私有的mixin 操作对象,将其它对象的属性方法拷贝到目标对象。

  Underscore.js 的 _.extend,把第二个参数起的所有对象都拷贝到第一个参数

1.掺合对象 (Mixin object)

先看最简单的mixin实现

function mixin(dest, src) {
for (var key in src) {
dest[key] = src[key]
}
} //使用下 var person = {name: 'yudi', age: 24}
var obj = {}
mixin(obj, person)
console.log(obj) // {name: 'yudi', age: 24}

上面的已经将person的所有属性拷贝到obj上了。 但有个缺陷,如果obj上已经有了name: 'rain',那么会被person覆盖。因此需要加个判断,如果dest上已经存在了,就不拷贝。

function mixin(dest, src) {
for (var key in src) {
if (!dest[key]) {
dest[key] = src[key]
}
}
}
//使用
var person = {name: 'yudi', age: 24}
var obj = {name: 'rain'}
mixin(obj, person)
console.log(obj) // Object { name="yudi", age=24}

当然,你可以提供更强大,灵活的Mixin,比如可以将任意多个对象掺合到目标对象

function mixin(dest /*, Any number of objects */) {
var sources = Array.prototype.slice.call(arguments, 1)
for (var i=0; i<sources.length; i++) {
var src = sources[i]
for (var key in src) {
if (!dest[key]) {
dest[key] = src[key]
}
}
}
}
//使用
var person = {name: 'John', age: 29, toString: function(){return 'aa'}}
var permission = {open: 1}
var obj = {name: 'Jack'}
mixin(obj, person, permission)
console.log(obj) // Object { name="Jack", age=29, open=1}

2.掺和类(Mixin Classes)

有的翻译过来叫做掺元类,它是一种不需要用到严格的继承就可以复用代码的一种技术。如果多个类想用到某个类的某个方法,可以通过扩充这些类的原型已达到共享该方法。比如先创建一个包含各种通用方法的类,然后让其它类扩充于它。这个包含通用方法的类就叫掺元类。多数时候它不会直接实例化或调用,而是作为其它类的模板用于扩充。

先看最简单的实现

// 工具方法,实现mixin
function augment(destClass, srcClass) {
var destProto = destClass.prototype
var srcProto = srcClass.prototype
for (var method in srcProto) {
if (!destProto[method]) {
destProto[method] = srcProto[method]
}
}
} function Person() {} // 具有两个方法的类,用于mixin
Person.prototype.getName = function() {}
Person.prototype.getAge = function() {} function Student() {} // 没有任何方法的类 augment(Student, Person) // 调用,拷贝 var s1 = new Student()
console.log(s1) // Student { getName=function(), getAge=function()}

工具函数augment接受两个参数,都是函数类型(类),第一个类会从第二个类的原型上继承其方法。即使用Person类扩充了Student类。

我们知道,某些语言如C++/Python允许子类继承多个父类,但在JavaScript中是不允许的,因为一个构造器只有一个原型对象,不过这可以通过多个掺元类的方式实现扩充,这实际是一种变相多继承的实现。和mixin方法类似,修改下augment方法。

function augment(destClass, /*, Any number of classes */) {
var classes = Array.prototype.slice.call(arguments, 1)
for (var i=0; i<classes.length; i++) {
var srcClass = classes[i]
var srcProto = srcClass.prototype
var destProto = destClass.prototype
for (var method in srcProto) {
if (!destProto[method]) {
destProto[method] = srcProto[method]
}
}
}
} //这样就实现了多继承。

有时不想继承所有的方法,指向拷贝指定的方法,增加一个参数methods

function augment(destClass, srcClass, methods) {
var srcProto = srcClass.prototype
var destProto = destClass.prototype
for (var i=0; i<methods.length; i++) {
var method = methods[i]
if (!destProto[method]) {
destProto[method] = srcProto[method]
}
}
}
function Person() {}
Person.prototype.getName = function() {}
Person.prototype.setName = function() {}
Person.prototype.getAge = function() {}
Person.prototype.setAge = function() {} function Student() {} augment(Student, Person, ['getName', 'setName'])
var s1 = new Student()
console.log(s1) // Student { getName=function(), setName=function()}

  

掺合模式(Mixin)的更多相关文章

  1. javascript模式——Mixin

    Mixin是一种扩展收集功能的方式,能提高代码的复用率. 在javascript中,原型可以继承于其它对象的原型,并且可以为任意数量的实例定义属性.可以利用这一点来促进函数的复用. 下面一段代码就是将 ...

  2. Matlab混入模式(Mixin)

    Mixin是一种类,这种类包含了其他类要使用的特性方法,但不必充当其他类的父类.Matlab无疑是支持多继承的.我们可以利用 Matlab 的这种特性,实现一种叫做 Mixin 的类.MixIn的目的 ...

  3. Mixin模式

    Mixin是JavaScript中用的最普遍的模式,几乎所有流行类库都会有Mixin的实现. Mixin是掺合,混合,糅合的意思,即可以就任意一个对象的全部或部分属性拷贝到另一个对象上. 从提供的接口 ...

  4. 设计模式 Mixin (混入类)

    混入(mix-in)类代表类之间的另一种关系.在C++中,混入类的语法类似于多重继承,但是语义完全不同.混入类回答"这个类还可以做什么"这个问题,答案经常以"-able& ...

  5. Python的Mixin

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826299.html 一:Mixin模式 Mixin编程是一种开发模式,是一种 将多个不同类中的功能单元的 ...

  6. Python SocketServer源码分析

    1      XXXServer 1.1      BaseSever 提供基础的循环等待请求的处理框架.使用serve_forever启动服务,使用shutdown停止.同时提供了一些可自行扩展的方 ...

  7. JavaScript的学习--JavaScript设计模式的总结

    这篇博客只是自己对设计模式的理解的备忘~ 看完了<JavaScript设计模式>这本书,一直没有写博客记录一下,最近抽出时间来重读了一下,就顺便记录一下~ 如果你只是想粗略了解一下Java ...

  8. ES6(六) --- Symbol

    概述: ES5 中属性名都是字符串,这容易就造成命名的冲突,特别是在混入模式(mixin模式)下.为解决这个问题ES6 引入了Symbol, Symbol是一种新的基本数据类型,表示独一无二的值!   ...

  9. Python设计模式 - 基础 - 封装 & 继承 & 多态

    面向对象的核心是对象,世间万物都可以看作对象,任何一个对象都可以通过一系列属性和行为来描述,可以包含任意数量和类型的数据或操作.类是用来描述具有相同属性和方法的所有对象的集合.类通常是抽象化的概念,而 ...

随机推荐

  1. Tomcat服务器使用(二)

    1. 打包Javaweb应用 当开发人员在自己的开发机器上调试所有代码并通过后,为了进行产品发布,都需要将开发人员的源码打包成war包进行发布.之前已经了解了jar包,那么war包和jar包的区别是什 ...

  2. (MVVM) ListBox Binding 和 实时刷新

    当需要用Lisbbox 来log 一些记录的时候,ObservableCollection 并不可以是记录实时的反应在WPF 的UI上面. 这个时候就需要用一个异步collection 来完成. // ...

  3. SpringBoot框架下基于Junit的单元测试

    前言 Junit是一个Java语言的单元测试框架,被开发者用于实施对应用程序的单元测试,加快程序编制速度,同时提高编码的质量.是一个在发展,现在已经到junit5,在javaEE开发中与很多框架相集成 ...

  4. C++ 友元(系转载多人博客,添加个人见解)

    原文地址:http://blog.csdn.net/caroline_wendy/article/details/16916441 原文地址:http://www.cnblogs.com/CBDoct ...

  5. 动态注册broadcast的安全考虑

    一.android service通知activity更新方式有1. service 通过广播的形式发送broadcast,向这个activity的内部类发广播的消息来更新界面2. service直接 ...

  6. php遍历数组赋值

    <?php $arr=array( array("num"=>100,"name"=>"Liuxy","scor ...

  7. Java任务调度框架Quartz入门

    Quartz[kwɔːts]:石英,其框架和名字一样简单朴素又不失魅力,在Java程序界,Quartz大名鼎鼎,很多Java应用几乎都集成或构建了一个定时任务调度系统,Quartz是一个定时任务调度框 ...

  8. 从Linux访问Windows共享目录

    今天装备用VMWare装台Linux服务器来学习Oracle数据库,由于安装包是下载到本地的Windows系统,需要拷贝到Linux虚机里面去.搞了半天.想到虚机网络设成桥接,然后访问.百度了一下.最 ...

  9. 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果

    学习笔记---Javascript事件Event.IE浏览器下的拖拽效果     1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...

  10. vim的visual模式

    在可视化模式下,可以对一个文本块的整体进行操作.例如,首先高亮选中一部分文本,然后用d命令删除这个文本块.可视化模式的好处在于,你可以在做改动之前,就看到操作将影响的文本.可视化模式可以分为以下三种: ...