Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
186 views
in Technique[技术] by (71.8m points)

javascript - JavaScript:对象的filter()(JavaScript: filter() for Objects)

ECMAScript 5 has the filter() prototype for Array types, but not Object types, if I understand correctly.

(如果我理解正确的话,ECMAScript 5有Array类型的filter()原型,但不是Object类型。)

How would I implement a filter() for Object s in JavaScript?

(如何在JavaScript中为Object实现filter() ?)

Let's say I have this object:

(假设我有这个对象:)

var foo = {
    bar: "Yes"
};

And I want to write a filter() that works on Object s:

(我想写一个适用于Objectfilter() :)

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

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

    return result;
};

This works when I use it in the following demo, but when I add it to my site that uses jQuery 1.5 and jQuery UI 1.8.9, I get JavaScript errors in FireBug.

(这在我在下面的演示中使用时有效,但是当我将它添加到使用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> 

  ask by AgileMeansDoAsLittleAsPossible translate from so


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First of all, it's considered bad practice to extend Object.prototype .

(首先, 扩展Object.prototype被认为是不好的做法 。)

Instead, provide your feature as utility function on Object , just like there already are Object.keys , Object.assign , Object.is , ...etc.

(相反,在Object上提供您的功能作为实用程序功能,就像已有Object.keysObject.assignObject.is ,...等。)

I provide here several solutions:

(我在这提供了几个解决方案)

  1. Using reduce and Object.keys

    (使用reduceObject.keys)

  2. As (1), in combination with Object.assign

    (如(1),与Object.assign结合使用)

  3. Using map and spread syntax instead of reduce

    (使用map和spread语法代替reduce)

  4. Using Object.entries and Object.fromEntries

    (使用Object.entriesObject.fromEntries)

1. Using reduce and Object.keys(1.使用reduceObject.keys)

With reduce and Object.keys to implement the desired filter (using ES6 arrow syntax ):

(使用reduceObject.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); 

Note that in the above code predicate must be an inclusion condition (contrary to the exclusion condition the OP used), so that it is in line with how Array.prototype.filter works.

(请注意,在上面的代码predicate必须是包含条件(与OP使用的排除条件相反),因此它与Array.prototype.filter工作方式一致。)

2. As (1), in combination with Object.assign(2.如(1),与Object.assign结合使用)

In the above solution the comma operator is used in the reduce part to return the mutated res object.

(在上面的解决方案中,在reduce部分中使用逗号运算符来返回变异的res对象。)

This could of course be written as two statements instead of one expression, but the latter is more concise.

(这当然可以写成两个语句而不是一个表达式,但后者更简洁。)

To do it without the comma operator, you could use Object.assign instead, which does return the mutated object:

(要在没有逗号运算符的情况下执行此操作,您可以使用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. Using map and spread syntax instead of reduce(3.使用map和spread语法代替reduce)

Here we move the Object.assign call out of the loop, so it is only made once, and pass it the individual keys as separate arguments (using the spread syntax ):

(这里我们将Object.assign调用移出循环,因此它只进行一次,并将各个键作为单独的参数传递(使用扩展语法 ):)

 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. Using Object.entries and Object.fromEntries(4.使用Object.entriesObject.fromEntries)

As the solution translates the object to an intermediate array and then converts that back to a plain object, it would be useful to make use of Object.entries (ES2017) and to use a method that does the opposite (ie create an object from an array of key/value pairs ).

(当解决方案将对象转换为中间数组然后将其转换回普通对象时,使用Object.entries (ES2017)并使用相反的方法(即从中创建对象 )将非常有用。 键/值对数组 )。)

At the time of writing the Object.fromEntries proposal is at stage 3. Firefox and, more recently, Chrome have implemented it .

(在撰写本文时, Object.fromEntries提案已进入第3阶段.Firefox以及最近Chrome已实现它 。)

Otherwise a polyfill can be used.

(否则可以使用填充物。)

It leads to these two "one-liner" methods on Object (including the polyfill):

(它导致Object上的这两个“单线”方法(包括polyfill):)

 Object.fromEntries = arr => Object.assign({}, ...arr.map( ([k, v]) => ({[k]: v}) )); 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); 

The predicate function gets a key/value pair as argument here, which is a bit different, but allows for more possibilities in the predicate function's logic.

(谓词函数在这里获得一个键/值对作为参数,这有点不同,但在谓词函数的逻辑中允许更多的可能性。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...