繁体   English   中英

如何使用Array.prototype.filter过滤对象?

[英]How to filter Object using Array.prototype.filter?

特定

var arr = [1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]]

我们可以使用Number构造函数过滤数组arr数字项

var res = arr.filter(Number); // [1, 2, true, 4, 6, 7, 9, Array[1]]

在结果数组中是true[10]期望? 如果我们替换falsetrue ,在arr

var arr = [1,2,false,4,{"abc":123},6,7,{"def":456},9,[10]] 
var res = arr.filter(Number) // [1, 2, 4, 6, 7, 9, Array[1]]

使用Array.isArray

var res = arr.filter(Array.isArray) // [Array[1]]

String

var res = arr.filter(String) // [1, 2, true, 4, Object, 6, 7, Object, 9, Array[1]]

如果我们要过滤中的项目arr是对象,在指数47 ,我们尝试

var res = arr.filter(Object) // [1, 2, true, 4, Object, 6, 7, Object, 9, Array[1]]

虽然我们更愿意简单地调用arr.filter(Object) ,但我们可以传递一个函数调用; 尝试使用Object不同属性,这样我们最终可以找到一个属性或方法,我们可以将它们用作函数或构造函数来传递给模式arr.filter(/* method, constructor, other approach */)以返回过滤结果匹配对象,甚至是输入数组中对象的属性名称或值。

我们通过检查数组中的项是否具有name等于"Object"constructor来无辜地开始

 var res = arr.filter(function(prop) {
  return prop.constructor.name === "Object"
 }) // [Object, Object]

虽然当我们向arr添加一个对象时; 例如;

 var c = Object.create(null); arr.push(c); 

 var res = arr.filter(function(prop) {
   return prop.constructor.name === "Object"
 }) // `Uncaught TypeError: Cannot read property 'name' of undefined`

因为c prototypeconstructorundefined 虽然我们确信这不会返回预期的结果

var n = arr.filter(Object.hasOwnProperty, "abc"); // [1, 2]

至少没有返回错误; 让我们继续吧

var n = arr.filter(function(prop, val) {
          return prop.hasOwnProperty(this.valueOf())
        }, "abc"); // [Object abc: 123__proto__: Object]

返回预期结果; 虽然我们正在尝试使用

var n = arr.filter(/* function reference */, this /* optional parameters passed */)

  1. 过滤Object{}对象的数组; 即使对象没有定义的原型或构造函数; 可选地将JSON字符串"{"abc":123}"为对象; 虽然我们还没到达这个目的,但是;

  2. 将属性名称传递给.filter(callback, this)模式,其中this用作属性名称或对象的值; 或使用利用的方法filter.bind.call.apply或其他方法来筛选来自输入数组的对象-不使用全

    .filter(function(prop, value) {})

    图案。 我们如何将Object.hasOwnProperty()调用强制转换为类似于的模式

    .filter(Object.hasOwnProperty, "abc")

提起.call.bind.apply寻找一个类似的问题,并找到后对原型法JS Array.prototype.filter 虽然不确定如何实现在过滤具有如上所述的特定属性的对象和对象中描述的方法。

注意,问题也可以通过destructuring或其他es-6es-7方法解决,与.filter()相比,提供可比较的甚至更严格的结果。 也就是说,不使用.filter()

   function(prop, value) {

   }

图案。 归还对象; 那是Object{} ; 和按属性过滤的对象; 按属性值过滤的对象。


问题:

  1. 如何在不使用匿名函数callback模式的情况下,在传递给Array.prototype.filter()的数组中使用或不使用Object原型或构造函数来过滤对象?

  2. 如何通过将属性名称或值传递给匹配对象而不使用匿名函数callback模式来过滤传递给Array.prototype.filter()的数组中的特定对象?

如何在不使用匿名函数callbackpattern的情况下,在传递给Array.prototype.filter()的数组中使用或不使用Object原型或构造函数来过滤对象?

根据规格

callbackfn应该是一个接受三个参数的函数,并返回一个可以强制转换为布尔值true或false的值

Number对象 (函数的构造函数)确实返回NaN以进行错误的Number转换,但String和Object构造函数不返回false值(是的, filter(Number)也过滤掉0)

var arr = [0,1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]];
arr.filter(Number); //outputs [1, 2, true, 4, 6, 7, 9, Array[1]]

您可以创建客户功能OBJ,

function OBJ(value,index,arr){ return typeof value === "object" && !Array.isArray(value) }

或者在结果Array.isArray也欢迎使用Arrays,然后删除Array.isArray检查

function OBJ(value,index,arr){ return typeof value === "object" }

与...一起使用时

arr.filter(OBJ); //outputs [{"abc":123},{"def":456}]

没有创建自己的功能,没有真正的安全方法。 此外,它非常复杂,因为Object的定义过于宽泛。

让我们从以下开始:

var types = ['1', 2, true, null, undefined, [], {}, new Date()];

并运行以下内容:

types.map((e) => typeof e);
// ["string", "number", "boolean", "object", "undefined", "object", "object", "object"]

你认为作为Objectnull吗? 我不这么认为。 你是否认为一个Array作为Object ,因为Array Object一个实例? 我也不确定。

您可以尝试以下内容:

types.map(Object.isExtensible);
// [false, false, false, false, false, true, true, true]

这会从结果中排除null ,但此处仍然存在数组。 Date Object在这里以及任何其他具有任何prototype Object ,例如new Boolean()也将是一个Object 此外,该对象可能被冻结,这也不会作为Object返回。

因此,这两个示例都成功地证明了Object的定义过于宽泛,并且无法以有用的方式进行真正的处理。

您似乎想要为具有特定类型的元素过滤数组。 通过适当的功能filter

array.filter(istype("String"))

您只需要立即编写istype

function istype(type) {
  return function(x) {
    return Object.prototype.toString.call(x) === '[object ' + type + ']';
  }
}

您似乎认为可以通过说过filter(Number)等来过滤数字。但这不起作用。 Number只是另一个函数,它试图将某些东西变成一个数字( 检查它是否是一个数字)。 然后, filter器过滤数组,具体取决于结果是真或假。 Number将产生任何非零数量truthy值明显和true 对于一个字符串,一个对象,或几乎任何其他东西,它将返回NaN,这是假的,有奇怪的例外,例如为[]返回0或全空字符串。

与字符串相同。 String只是另一个函数,它试图将某些东西变成一个字符串。 然后, filter器过滤数组,具体取决于结果是真或假。 String将为除非空字符串之外的任何其他内容生成一个truthy值。

这与解构没有任何关系; 为什么你会这么想? 您可能想删除帖子中那个不幸的部分。 使用回调来确定过滤哪些元素和流出是整个DNA -也不清楚你所说的“没有回调调用过滤器”的意思filter 当你说出function(prop, value) { }模式时,你也不清楚你指的是什么模式。

在问题的最后,您提出两个具体问题:

如何在不使用匿名函数callbackpattern的情况下,在传递给Array.prototype.filter()的数组中使用或不使用Object原型或构造函数来过滤对象?

您可以通过提供确定特定元素是否为对象的函数来过滤输入数组中的对象。 这不是对象原型或构造函数Object ,因此对您没有帮助。 你必须编写一个小函数来传递filter ,这就是它的工作原理。 它可以是匿名的,也可以在别处定义并传入

如何通过将属性名称或值传递给匹配对象而不使用匿名函数回调模式来过滤传递给Array.prototype.filter()的数组中的特定对象?

“将属性名称或值传递给匹配对象”是什么意思? 您的意思是,过滤掉缺少特定属性名称或值的元素? 然后编写一个函数来做到这一点。 如果这是正在寻找的内容,则没有用于此目的的内置函数。

在不传递回调函数的情况下,您可以使用RegExp.prototype.test方法传递正则表达式并绑定正则表达式

 var arr = [1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]] var res = arr.filter(RegExp.prototype.test.bind(/\\[object Object\\]/)); console.log(res) 

这也会匹配包含[object Object]任何字符串,但是字符串似乎不太可能包含那些确切的单词,除非您犯了错误并在数组中包含了字符串化对象。

在ES6中,以下将针对您列出的示例值执行此操作:

arr.filter(Object.isExtensible)

显然,这将通过调用Object.freezeObject.sealObject.preventExtensions来排除已标记为不可扩展的对象。 除非你打算使用它们,否则我相信这是有用的。

 var arr = [ /* primitives: */ 2, true, "str", null, undefined, NaN, /* objects */ new Number(2), {a:1}, Object.create(null), [10], x=>x, new Date(), new Set() ]; var objects = arr.filter(Object.isExtensible); console.log(objects); 

到目前为止最接近要求,也匹配Object.create(null)

var res = []; for (let p of arr) /^\{?.+\}$/.test(JSON.stringify(p)) && res.push(p)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM