javascript的Mixins
mixin在javascript里可以看作是一种从别的对象"借用"功能的方法。每一个新定义的对象都有一个 prototype属性,其他的对象就可以从这里"借用"功能。这里的功能可以是一个属性,也可以是一个方法。

mixins这种借用在 javascript里非常的适用。在重用代码的时候可以使用mixins来实现继承,也可以达到类似多继承的效果。假设我们定义了这么一个对象:
var myMixins = {
moveUp: function(){
console.log( "move up" );
},
moveDown: function(){
console.log( "move down" );
},
stop: function(){
console.log( "stop! in the name of love!" );
}
};
我们可以非常容易的使用一个helper来扩展现有的对象。比如使用Underscore.js的extend()方法:
// A skeleton carAnimator constructor
function carAnimator(){
this.moveLeft = function(){
console.log( "move left" );
};
}
// A skeleton personAnimator constructor
function personAnimator(){
this.moveRandomly = function(){ /*..*/ };
}
// Extend both constructors with our Mixin
_.extend( carAnimator.prototype, myMixins );
_.extend( personAnimator.prototype, myMixins );
// Create a new instance of carAnimator
var myAnimator = new carAnimator();
myAnimator.moveLeft();
myAnimator.moveDown();
myAnimator.stop();
// Outputs:
// move left
// move down
// stop! in the name of love!
从代码可以看到,这个mixins实现的非常简单。在下一个例子中我们会使用两个构造函数:一个Car,一个Mixin。我们要做的就是使用一个自定义的argument方法来扩展Car,这样Car可以从Mixin里"借用"某些特定的方法。比如,driveForward()和driveBackword()。这次我们不使用Underscore.js。
这里例子会非常清楚的展示argument方法是怎么达到"借用"效果的:
// Define a simple Car constructor
var Car = function ( settings ) {
this.model = settings.model || "no model provided";
this.color = settings.color || "no colour provided";
};
// Mixin
var Mixin = function () {};
Mixin.prototype = {
driveForward: function () {
console.log( "drive forward" );
},
driveBackward: function () {
console.log( "drive backward" );
},
driveSideways: function () {
console.log( "drive sideways" );
}
};
// Extend an existing object with a method from another
function augment( receivingClass, givingClass ) {
// only provide certain methods
if ( arguments[2] ) {
for ( var i = 2, len = arguments.length; i < len; i++ ) {
receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];
}
}
// provide all methods
else {
for ( var methodName in givingClass.prototype ) {
// check to make sure the receiving class doesn't
// have a method of the same name as the one currently
// being processed
if ( !Object.hasOwnProperty(receivingClass.prototype, methodName) ) {
receivingClass.prototype[methodName] = givingClass.prototype[methodName];
}
// Alternatively:
// if ( !receivingClass.prototype[methodName] ) {
// receivingClass.prototype[methodName] = givingClass.prototype[methodName];
// }
}
}
}
// Augment the Car constructor to include "driveForward" and "driveBackward"
augment( Car, Mixin, "driveForward", "driveBackward" );
// Create a new Car
var myCar = new Car({
model: "Ford Escort",
color: "blue"
});
// Test to make sure we now have access to the methods
myCar.driveForward();
myCar.driveBackward();
// Outputs:
// drive forward
// drive backward
// We can also augment Car to include all functions from our mixin
// by not explicitly listing a selection of them
augment( Car, Mixin );
var mySportsCar = new Car({
model: "Porsche",
color: "red"
});
mySportsCar.driveSideways();
// Outputs:
// drive sideways
好处和坏处
Mixins可以减少代码的重复增加代码的复用。如果一个对象需要使用其他对象已经定义的"功能"的时候,我们就可以使用mixins复用代码。这样就可以集中精力实现那么独一无二,确实非常需要的代码上。
但是,mixins也有值得商榷的一面。有很多开发者认为把方法注入到其他的对象里不是很好,这样会造成prototype污染,也会造成我们本来定义的对象的不确定性。这些确实会发生。
我个人觉得良好的文档会减少mixins的使用造成的困惑。而且,不管任何的模式。只要我们在开发的时候就考虑好它的利和弊,那么就会减少不必要的问题。
原文地址:https://www.safaribooksonline.com/library/view/learning-javascript-design/9781449334840/ch09s13.html
javascript的Mixins的更多相关文章
- JavaScript mixins
mixin 是一个类,该类的方法被添加,混合进另外一个类.一个基础类会包含mixin类的方法而不是继承它.这样你就可以使用不同的mixin类来增加或者增强基础类的功能. 这编内容包含怎么样使用java ...
- JavaScript Patterns 6.6 Mix-ins
Loop through arguments and copy every property of every object passed to the function. And the resul ...
- JavaScript面向对象之我见
序言 在JavaScript的大世界里讨论面向对象,都要提到两点:1.JavaScript是一门基于原型的面向对象语言 2.模拟类语言的面向对象方式.对于为什么要模拟类语言的面向对象,我个人认为:某些 ...
- ES6新特性:使用新方法定义javascript的Class
ES6中定义类的方式, 就是ES3和ES5中定义类的语法糖,虽然也有些区别,但是整体定义类的方式更加简洁,类的继承更加方便, 如果想对ES6中的继承更加熟悉, 最好了解ES5中原型继承的方式, 博客园 ...
- TypeScript & JavaScript
http://www.typescriptlang.org/docs/tutorial.html handbook: Basic Types Variable Declarations Interfa ...
- a primary example for Functional programming in javascript
background In pursuit of a real-world application, let’s say we need an e-commerce web applicationfo ...
- EXTJS4自学手册——EXT基本方法、属性(mixins多继承、statics、require)
1.mixins 说明:类似于面向对象中的多继承 <script type="text/javascript"> Ext.onReady(function () {// ...
- Javascript.ReactNative-2-javascript-syntax-in-react-native
JavaScript Syntax in React Native Contents: Arrow Function Let+Const Default + Rest + Spread Destruc ...
- 大型 JavaScript 应用架构中的模式
原文:Patterns For Large-Scale JavaScript Application Architecture by @Addy Osmani 今天我们要讨论大型 JavaScript ...
随机推荐
- Linux驱动之建立一个hello模块
目标:在开发板上执行insmod hello.ko能在控制台打印出hello init:接着执行rmmod会在控制台打印出hello exit 建立一个hello模块的步骤如下: 1.建立一个hell ...
- 基于Confluent.Kafka实现的KafkaConsumer消费者类和KafkaProducer消息生产者类型
一.引言 研究Kafka有一段时间了,略有心得,基于此自己就写了一个Kafka的消费者的类和Kafka消息生产者的类,进行了单元测试和生产环境的测试,还是挺可靠的. 二.源码 话不多说,直接上代码,代 ...
- git bug修复
在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除. 当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支i ...
- Liunx read
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量 1)read后面的变量var可以只有一个,也可以有多个,这时如果输入多个数据,则第一个数据给第一个变量,第二个数据 ...
- accept与epoll惊群 转载
今天打开 OneNote,发现里面躺着一篇很久以前写的笔记,现在将它贴出来. 1. 什么叫惊群现象 首先,我们看看维基百科对惊群的定义: The thundering herd problem occ ...
- [SoapUI] Groovy获取HTTP Status
def value = messageExchange.responseHeaders["#status#"] def httpResponseHeaders = context. ...
- [规则原则定理]规则原则定理章3Java命名规范
JAVA命名规范 驼峰法则: 将所有字母都小写(包括缩写),然后将单词的第一个字母大写. 每个单词的第一个字母都大写,来得到大驼峰式命名. 除了第一个单词,每个单词的第一个字母都大写,来得到(小)驼峰 ...
- [Spark]What's the difference between spark.sql.shuffle.partitions and spark.default.parallelism?
From the answer here, spark.sql.shuffle.partitions configures the number of partitions that are used ...
- python连接Linux服务器
import paramikoimport os #当前脚本路径CUR_PATH = os.path.dirname(__file__) #服务器ipHost=''Port=22#登录用户名Usern ...
- 各种编译不通过xcode
2017-08-24 Apple Mach-O Linker (Id) Error Linker command failed with exit code 1 (use -v to see invo ...