您的位置:首页 > Web前端 > JavaScript

javascript的Mixins

2016-06-21 21:33 375 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: