文档章节

掺合模式(Mixin)

iNiL0119
 iNiL0119
发布于 2015/03/29 17:26
字数 1146
阅读 104
收藏 7

掺合模式(Mixin)

Mixin是JavaScript中用的最普遍的模式,几乎所有流行类库都会有Mixin的实现。

Mixin是掺合,混合,糅合的意思,即可以就任意一个对象的全部或部分属性拷贝到另一个对象上。

从提供的接口来看,有的是对对象的操作,有的是对类的操作。对类的操作又称为掺元类(Mixin classes)

 

一、掺合对象 (Mixin object)

先看最简单的mixin实现

function mixin(dest, src) {
    for (var key in src) {
        dest[key] = src[key]
    }
}

使用下

var person = {name: 'John', age: 29}
var obj = {}
mixin(obj, person)
console.log(obj) // {name: 'John', age: 29}

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

function mixin(dest, src) {
    for (var key in src) {
        if (!dest[key]) {
            dest[key] = src[key]
        }
    }
}
var person = {name: 'John', age: 29}
var obj = {name: 'Jack'}
mixin(obj, person)
console.log(obj) // Object { name="Jack", age=29}

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

function mixin(dest, src) {
    for (var key in src) {
        if (!dest[key]) {
            dest[key] = src[key]
        }
    }
}
var person = {name: 'John', age: 29}
var obj = {name: 'Jack'}
mixin(obj, person)
console.log(obj) // Object { name="Jack", age=29}


以下类库都是对对象的掺合

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

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

  • ExtJS的Ext.apply 也是操作对象,它还提供了一个defaults参数。

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

 

二、掺和类(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()}


Backbone是广泛使用掺元类的库

首先,Backbone库自身就采用Mixin classes方式组织,如Backbone.Events是最底层的掺元类,它的方法(on/off/trigger...)都被Backbone.Model/Backbone.Collection/Backbone.View等继承。代码片段如下

_.extend(Model.prototype, Events, {
    ...
})
_.extend(Collection.prototype, Events, {
    ...
})
_.extend(View.prototype, Events, {
    ...
})

它这里使用_.extend来扩充Model,Collection,View的原型,把Events的方法都拷贝到原型。即Event就是一个掺元类(虽然被实现为一个对象)

 

其次,我们使用Backbone开发时,你写的模型会用Backbone.Model去扩充,视图会用Backbone.View去扩充。如

var MyModel = Backbone.Model.extend({
    instanceProp: xx
},{
    classProp: yy
})
 
var MyView = Backbone.Model.extend({
    instanceProp: xx
},{
    classProp: yy
})

这时,Backbone.Model/Backbone.View等就是掺元类了。当然,你还可以把underscore当做掺元对象,因为Backbone的很多类都继承了_.extend方法,如Backbone.Events/Backbone.Model等。


原文出处:http://www.cnblogs.com/snandy/archive/2013/05/24/3086663.html

© 著作权归作者所有

共有 人打赏支持
iNiL0119
粉丝 6
博文 90
码字总数 88887
作品 0
杭州
前端工程师
0基础,想掺合一下微信新开的应用号,都需要学什么啊?求指教,求带!

0基础,想掺合一下微信新开的应用号,都需要学什么啊?求指教,求带!

沉睡44214274
2016/09/29
99
4
「译」你的 mixin 兼容 ECMAScript 5 吗?

原文:Are your mixins ECMAScript 5 compatible? 作者:Nicholas C. Zakas 译文:你的 mixin 兼容 ECMAScript 5 吗? 译者:justjavac 好久没更新博客了,今天在 nczonline 看到了这篇博客,...

justjavac
2012/12/12
203
0
[译] 函数式 Mixin(软件编写)(第七部分)

原文地址:Functional Mixins 原文作者:本文已获原作者 Eric Elliott 授权 译文出自:掘金翻译计划 译者:yoyoyohamapi 校对者:Tina92 reid3290 Smoke Art Cubes to Smoke — MattysFli...

吴晓军
2017/06/21
0
0
笨鸟也能飞,我真的“开发”了一个第一个小程序

0.0 前言 世界很奇妙,在很久之前我曾经听到这样的一种观点——未来“编程”一定是每一个孩子的必修课。 这是惊人的,却也是自然的,但一直到2018年7月22日这一天,我第一次深刻的理解了这样...

PUPPET黄志华
07/24
0
0
SASS

一、sass的安装 sass安装博客网址:http://my.oschina.net/sundaren/blog/716055 二、准备和监听 1. sass的文件后缀名 : .scss(意思为Sassy CSS) 2.sass文件的转化: 3.提供四个编译风格的选项...

大仁孙
2016/07/22
5
0

没有更多内容

加载失败,请刷新页面

加载更多

学习设计模式——单例模式

1. 认识单例模式 1. 定义:一个类中仅有一个实例,并提供一个访问它的全局访问点。 2. 结构:仅一个Singleton类,其中包含一个static类变量,而类变量的类型就是Singleton类,而且Singleton...

江左煤郎
28分钟前
1
0
前端安全系列之二:如何防止CSRF攻击?

背景 随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一,而前端又是引发企业安全问题的高危据点。在移动互联网时代,前端人员除了传统的 XSS、CSRF 等安全问题之外,又时常...

talen
30分钟前
1
0
Mysql数据库大量删除操作及谈面向对象中的封装继承和多态原理(图)

Mysql数据库大量删除操作及谈面向对象中的封装继承和多态原理(图) 最近进行数据库操作,遇到一个问题,就是大量删除一个数据表中的数据后,由于设定了id是自增的,导致再插入时,默认生成的...

原创小博客
31分钟前
1
0
Springboot + mongoDB : So easy

1. dependancy compile('org.springframework.boot:spring-boot-starter-data-mongodb') 2. config # mongodbspring.data.mongodb.host=***.mongodb.rds.aliyuncs.comspring.data.mongod......

园领T
43分钟前
2
0
centos 7( linux )下安装elasticsearch教程

目录 概述 环境准备 elaticsearch简介 安装elasticsearch 彩蛋 概述 很久没有写博客了,最近在做全文检索的项目,发现elasticsearch踩了不少坑,百度点进去又是坑,在此记录一下自己的踩坑历程。...

java_龙
48分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部