私の理解が正しければ、 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.keys
、Object.assign
、Object.is
などと同様に、 のユーティリティ関数として提供します。
ここでいくつかの解決策を示します。
- 使用し
reduce
てObject.keys
- (1)と組み合わせると、
Object.assign
map
スプレッド構文の代わりに使用するreduce
- 使用し
Object.entries
てObject.fromEntries
1. 使用しreduce
てObject.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.entries
てObject.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);
ここでは述語関数がキーと値のペアを引数として取得します。これは少し異なりますが、述語関数のロジックにさらに多くの可能性が与えられます。