JavaScript: オブジェクトの filter() 質問する

JavaScript: オブジェクトの filter() 質問する

私の理解が正しければ、 ECMAScript 5には型filter()のプロトタイプはありますArrayが、Object型自体はありません。

JavaScript でfilter()forを実装するにはどうすればよいでしょうか?Object

次のようなオブジェクトがあるとします。

var foo = {
    bar: "Yes"
};

filter()そして、で動作するを書きたいと思いますObject:

Object.prototype.filter = function(predicate) {
    var result = {};

    for (key in this) {
        if (this.hasOwnProperty(key) && !predicate(this[key])) {
            result[key] = this[key];
        }
    }

    return result;
};

これは次のデモで使用すると機能しますが、jQuery 1.5 および jQuery UI 1.8.9 を使用するサイトに追加すると、FireBug で JavaScript エラーが発生します。

Object.prototype.filter = function(predicate) {
  var result = {};
  for (key in this) {
    if (this.hasOwnProperty(key) && !predicate(this[key])) {
      console.log("copying");
      result[key] = this[key];
    }
  }
  return result;
};

var foo = {
  bar: "Yes",
  moo: undefined
};

foo = foo.filter(function(property) {
  return typeof property === "undefined";
});

document.getElementById('disp').innerHTML = JSON.stringify(foo, undefined, '  ');
console.log(foo);
#disp {
  white-space: pre;
  font-family: monospace
}
<div id="disp"></div>

ベストアンサー1

初めに、延長するのは悪い習慣だと考えられているObject.prototype代わりに、機能をスタンドアロン関数として提供するか、本当にグローバルを拡張したい場合は、Object既に存在するObject.keysObject.assignObject.isなどと同様に、 のユーティリティ関数として提供します。

ここでいくつかの解決策を示します。

  1. 使用しreduceObject.keys
  2. (1)と組み合わせると、Object.assign
  3. mapスプレッド構文の代わりに使用するreduce
  4. 使用しObject.entriesObject.fromEntries

1. 使用しreduceObject.keys

reduceそしてObject.keys希望するフィルタを実装する(ES6を使用)矢印構文):

Object.filter = (obj, predicate) => 
    Object.keys(obj)
          .filter( key => predicate(obj[key]) )
          .reduce( (res, key) => (res[key] = obj[key], res), {} );

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1); 
console.log(filtered);

上記のコードでは包含条件( OPが使用した除外predicate条件とは反対)である必要があることに注意してください。Array.prototype.filter動作します。

2. (1)と組み合わせると、Object.assign

上記の解決策では、カンマ演算子reduceは、変更されたオブジェクトを返す部分で使用されますres。もちろん、1つの式ではなく2つの文で記述することもできますが、後者の方が簡潔です。コンマ演算子を使わずにこれを行うには、次のようにします。Object.assign代わりに、変更されたオブジェクトを返します

Object.filter = (obj, predicate) => 
    Object.keys(obj)
          .filter( key => predicate(obj[key]) )
          .reduce( (res, key) => Object.assign(res, { [key]: obj[key] }), {} );

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1); 
console.log(filtered);

3.mapスプレッド構文の代わりにreduce

Object.assignここでは、呼び出しをループの外に移動して1回だけ実行し、個々のキーを個別の引数として渡します(スプレッド構文):

Object.filter = (obj, predicate) => 
    Object.assign(...Object.keys(obj)
                    .filter( key => predicate(obj[key]) )
                    .map( key => ({ [key]: obj[key] }) ) );

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1); 
console.log(filtered);

4. 使用しObject.entriesObject.fromEntries

このソリューションでは、オブジェクトを中間配列に変換し、それをプレーンオブジェクトに戻すため、Object.entries(ES2017)とその逆(つまりキーと値のペアの配列からオブジェクトを作成する) とObject.fromEntries(ES2019)。

これは、次の「ワンライナー」メソッドにつながりますObject

Object.filter = (obj, predicate) => 
                  Object.fromEntries(Object.entries(obj).filter(predicate));

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};

var filtered = Object.filter(scores, ([name, score]) => score > 1); 
console.log(filtered);

ここでは述語関数がキーと値のペアを引数として取得します。これは少し異なりますが、述語関数のロジックにさらに多くの可能性が与えられます。

おすすめ記事