Beautiful Mixins -《Beautiful JavaScript》念书分享

刚开始,代码只是代码罢了。当代码多了,我们发清楚明了函数,以便代码能够重用。到厥后,我们的函数也越来越多,所以我们又发清楚明了别的一些编程观点。然则当我们沉迷于这些新观点的同时,我们能够就错过了一些近在眼前的优美事物……

类继续

类观点重要存在于面向对象编程中的,能够人人上学时都学过,比如Java、C#、Objective-C等面向对象言语。每一个实体都须要先要有一个类,这个类关于我们来讲是比较笼统的(不是说abstract class哦),然后子类还能够继续父类。

这觉得好像有点亚里士多德形而上学和分类法的滋味,但简朴来讲这就是面向对象的基本,在写出现实代码之前,你得先写出一些类、接口,然后类继续类、类完成接口……

现实上我们人类并非异常擅长分类,打个比如,一个按钮(Button),它应当是一个矩形(Rectangle),照样一个控件(Control)呢?我们能够让Button继续Rectangle,让Rectangle继续Control……等等,是否是有什么不对?

所以,面向对象的观点能够会在项目刚开始时就把你压垮,但这并非说面向对象就不好,只是有时候并不合适你的项目。

原型链继续

能够人人都晓得,JavaScript是不支撑class关键字的,由于JavaScript自身就不作为一个面向对象言语来设想,但并不阻碍人人想出种种招来完成class

JavaScript是基于原型链(Prototype)继续的,然则其诡异的写法能够让很多初学者望而生畏。

function Circle() {
  this.radius = 7;
}
Circle.prototype = {
  area: function () {
    return Math.PI * this.radius * this.radius;
  },
  grow: function () {
    this.radius++;
  },
  shrink: function () {
    this.radius--;
  }
};

在ES5以后,我们有了Object.create要领,好理解了一些。

var circle = Object.create({
  area: function () {
    return Math.PI * this.radius * this.radius;
  },
  grow: function () {
    this.radius++;
  },
  shrink: function () {
    this.radius--;
  }
}, {
  radius: {
    writable: true,
    configurable: true,
    value: 7
  }
});

只是第二参数用起来有点庞杂,实在就是跟Object.defineProperties()的参数一样,然则我们如今又有了ES6呀:

class Cicle {
  constructor() {
    this.radius = 7;
  }
  area() {
    return Math.PI * this.radius * this.radius;
  }
  grow() {
    this.radius++;
  }
  shrink() {
    this.radius--;
  }
}

这都是一些运用JavaScript完成class的例子,现实上,JavaScript还能够有别的一种重用代码的体式格局——Mixins。

Mixins

这就是我们本日的主题,近在眼前的优美事物,但可不是什么新观点,用过Ruby或Python的同砚,能够有所线人,Mixins的字面意义就是把东西掺合在一起。

在JavaScript我们有callapply,很轻易切换上下文,将种种互不相关糅合,到达Mixins的目标。

假定我们要做一个圆形按钮(RoundButton),它有两个特征:

  1. 是圆的

  2. 可点击

我们能够把这两个特征离别写做2个函数:

// 是圆的
var withCircle = function () {
  this.area = function () {
    return Math.PI * this.radius * this.radius;
  };
  this.grow = function () {
    this.radius++;
  };
  this.shrink = function () {
    this.radius--;
  }
}

// 可点击
var withClickable = function () {
  this.hover = function () {
    console.log('hovering');
  };
  this.press = function () {
    console.log('button pressed');
  };
  this.release = function () {
    console.log('button released');
  };
  this.fire = function () {
    this.action.fire();
  };
}

这是我们的圆形按钮:

var RoundButton = function(radius, label, action) {
  this.radius = radius;
  this.label = label;
  this.action = action;
};

如今我们要让给这个圆形按钮附上那两个特征:

withCircle.call(RoundButton.prototype);
withClickable.call(RoundButton.prototype);

var button = new RoundButton(4, 'yes!', function() {
  return 'you said yes!'
});
button1.fire(); // 输出 'you said yes!'

如许写,是否是霎时显得既简约又天然?让人一眼看懂代码在做什么。

固然这些附加特征的函数用的多了,也就创建了很多函数,这里能够简朴的用一个马上实行函数(Immediately Invoked Function Expression)的闭包来对其举行优化一下,以withCircle为例:

var withCircle = (function () {
  function area() {
    return Math.PI * this.radius * this.radius;
  }
  function grow() {
    this.radius++;
  }
  function shrink() {
    this.radius--;
  }
  return function () {
    this.area = area;
    this.grow = grow;
    this.shrink = shrink;
  };
})();

如许就不须要每次运用都新建函数了,从而节约更多的资本。

Advice

有时候,你没法确保某些函数能够会掩盖原有的功用,比方以下例子:

Button.prototype.press = function() {
  console.log('pressed');
};

// 这时候再用我们的 withClickable,就会掩盖掉 press
withClickable.call(Button.prototype);

这时候候我们应当采纳Advice,Twitter的Flight框架已供应了此功用:

var withClickable = function () {
  this.after('press', function () {
    console.log('press again.');
  });
};

withAdvice.call(Button.prototype);
withClickable.call(Button.prototype);

var button = new Button();
button.press(); // 输出 'pressed', 'press again.'

两个press并不会互相冲突,而是有先后顺序的实行,就相似经由过程addEventListener添加了多个事宜而不是直接修正onclick一样,详细细节能够参考Flight的API。

小结

作为一位程序员,我们也许在上学时就被灌输了面向对象的固有头脑,毕竟面向对象从上世纪90年代到如今,经久不衰,自在它的上风。然则在JavaScript中,假如你并不擅长面向对象的笼统思维,何不尝试一下Mixins呢?而且Mixins与类继续比拟,还能更好的解耦合,能够用于任何Object之上,恰好用上了JavaScript若范例的上风。

近来在读《Beautiful JavaScript》这本书,有一些好的内容,恰好能够跟人人分享,但并非悉数,有兴致的同砚也能够本身读一下,请支撑正版。

原文链接:http://t.cn/RteECIF
微信号:程序员升级之路『code-learning』

《Beautiful Mixins -《Beautiful JavaScript》念书分享》

    原文作者:learning
    原文地址: https://segmentfault.com/a/1190000006724646
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞