JavaScript:对象的filter()
如果我理解正确,ECMAScript 5具有Array
types的filter()
原型,但不包含Object
types。
我将如何实现一个filter()
在JavaScript中的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>
永远不要扩展Object.prototype
。
可怕的事情会发生在你的代码。 事情会打破。 您正在扩展所有对象types,包括对象文字。
下面是一个可以尝试的简单例子:
// Extend Object.prototype Object.prototype.extended = "I'm everywhere!"; // See the result alert( {}.extended ); // "I'm everywhere!" alert( [].extended ); // "I'm everywhere!" alert( new Date().extended ); // "I'm everywhere!" alert( 3..extended ); // "I'm everywhere!" alert( true.extended ); // "I'm everywhere!" alert( "here?".extended ); // "I'm everywhere!"
而是创build一个你传递对象的函数。
Object.filter = function( obj, predicate) { var result = {}, key; // ---------------^---- as noted by @CMS, // always declare variables with the "var" keyword for (key in obj) { if (obj.hasOwnProperty(key) && !predicate(obj[key])) { result[key] = obj[key]; } } return result; };
您也可以使用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);
如果你愿意使用下划线或lodash ,你可以使用pick
(或者相反, omit
)。
下划线的文档示例:
_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age'); // {name: 'moe', age: 50}
或者用callback(对于lodash ,使用pickBy ):
_.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) { return _.isNumber(value); }); // {age: 50}
正如帕特里克已经表示,这是一个坏主意,因为它几乎肯定会打破任何第三方代码,你可能会希望使用。
如果扩展Object.prototype
,所有库(如jquery或prototype)都会中断,原因是由于添加的函数将成为迭代的一部分,所以对对象的懒惰迭代(不包含hasOwnProperty
检查)将会中断。
我已经创build了一个Object.filter()
,它不仅可以通过函数进行过滤,还可以接受包含的数组。 可选的第三个参数将允许您反转filter。
鉴于:
var foo = { x: 1, y: 0, z: -1, a: 'Hello', b: 'World' }
阵:
Object.filter(foo, ['z', 'a', 'b'], true);
function:
Object.filter(foo, function (key, value) { return Ext.isString(value); });
码
免责声明 :为了简洁,我select使用Ext JS内核。 没有觉得有必要为对象types编写types检查器,因为它不是问题的一部分。
// Helper functions function clone(obj) { return JSON.parse(JSON.stringify(obj)); } function print(obj) { document.getElementById('disp').innerHTML += JSON.stringify(obj, undefined, ' ') + '<br />'; console.log(obj); } Object.filter = function (obj, ignore, invert) { if (ignore === undefined) { return obj; } invert = invert || false; var not = function(condition, yes) { return yes ? !condition : condition; }; var isArray = Ext.isArray(ignore); for (var key in obj) { if (obj.hasOwnProperty(key) && (isArray && not(!Ext.Array.contains(ignore, key), invert)) || (!isArray && not(!ignore.call(undefined, key, obj[key]), invert))) { delete obj[key]; } } return obj; }; var foo = { x: 1, y: 0, z: -1, a: 'Hello', b: 'World' }, bar = clone(foo); print(Object.filter(foo, ['z', 'a', 'b'], true)); print(Object.filter(bar, function (key, value) { return Ext.isString(value); }));
#disp { white-space: pre; font-family: monospace }
<script src="ajax/libs/extjs/4.2.1/builds/ext-core.min.js"></script> <div id="disp"></div>
怎么样:
function filterObj(keys, obj) { const newObj = {}; for (let key in obj) { if (keys.includes(key)) { newObj[key] = obj[key]; } } return newObj; }
要么…
function filterObj(keys, obj) { const newObj = {}; Object.keys(obj).forEach(key => { if (keys.includes(key)) { newObj[key] = obj[key]; } }); return newObj; }
特定
object = {firstname: 'abd', lastname:'tm', age:16, school:'insat'}; keys = ['firstname', 'age'];
然后 :
keys.reduce((a, b) =>{ a[b]=object[b] ; return a},{}); // {firstname:'abd', age: 16}