LoginSignup
7
7

More than 5 years have passed since last update.

underscore.jsを読む#3 any,find,filter,reject

Last updated at Posted at 2014-05-06

第三回。

any.js
var any = _.some = _.any = function(obj, predicate, context) {
  predicate || (predicate = _.identity);
  var result = false;
  if (obj == null) return result;
  if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
  each(obj, function(value, index, list) {
    if (result || (result = predicate.call(context, value, index, list))) return breaker;
  });
  return !!result;
};

ネイティブではsome関数になります。基本的にはeachで順番にテストしていき、predicateがtrueになる要素が見つかったらbreakします。breakはbreakerを返すことで実現しています。

breakerはunderscore内でのみ参照可能な変数で空のオブジェクトが代入されています。したがって、eachに渡す関数が空のオブジェクトを返したとしてもbreakは起こらず、underscore内の関数のみが安全にbreakできます。

最後の「!!」はresultにboolean以外のものが代入された場合に、booleanを返せるようにするイディオムです(たぶん、、、)。

find.js
_.find = _.detect = function(obj, predicate, context) {
  var result;
  any(obj, function(value, index, list) {
    if (predicate.call(context, value, index, list)) {
      result = value;
      return true;
    }
  });
  return result;
};

anyで順番にテストしていって見つかったら早期終了して返すだけですね。見つからなかったらundefinedにするのは仕様のようです。

filter.js
_.filter = _.select = function(obj, predicate, context) {
  var results = [];
  if (obj == null) return results;
  if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
  each(obj, function(value, index, list) {
    if (predicate.call(context, value, index, list)) results.push(value);
  });
  return results;
};

これもeachで回してテストをパスするやつをpushしていくだけです。ちなみにリーダブルコードではfilterという名前は曖昧だから使うなとありました。まぁネイティブの実装がfilterという名前だから合わせたのでしょうけど。

reject.js
_.reject = function(obj, predicate, context) {
  return _.filter(obj, function(value, index, list) {
    return !predicate.call(context, value, index, list);
  }, context);
};

filterを使うとrejectは論理を反転させるだけで作れます。

Annotated Sourceにも書いています

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7