检查过滤器方法内部是否存在对象键?

时间:2019-04-05 14:57:16

标签: javascript

在过滤器中,我需要测试各种条件。

filter(books, (book) => {

    return myFilters.authors.map(a => a.id).includes(book.author_id) &&
    myFilters.skus.map(a => a.id).includes(book.sku);
    ....

还有其他条件取决于过滤器的类型,例如myFilters.price将是另一种测试。

我只是想知道您是否可以在过滤器内部进行测试时向我指出正确的方向,就像myFilter没有任何作者一样,map方法将失败。如何测试authors上存在的myFilters(使用类似authors in myFilters的{​​{1}}方法内部的filter

类似的东西:

filter(books, (book) => {

    return DOES AUTHORS EXIST ON MY FILTERS? myFilters.authors.map(a => a.id).includes(book.author_id) &&
    DO SKUS EXIST ON MY FILTERS? myFilters.skus.map(a => a.id).includes(book.sku);
    ....

2 个答案:

答案 0 :(得分:2)

当一个空数组不存在时,可以使用逻辑Group OR运算符替换一个空数组。

||

但是我认为最好是能够控制结构以使其始终有一个数组,即使它是空的。


如果在数组不存在时需要排除过滤器的那部分,请使用条件运算符。

return (myFilters.authors || []).map(...)

但是,实际上似乎在这里单独的功能将是有益的。像这样:

return (myFilters.author ? myFilters.authors.map(...).includes(...) : true) &&
       (myFilters.skus ? myFilters.skus.map(...).includes(...) : true)

然后:

function includesIfExists(arr, prop, val) {
  return arr ? arr.map(v => v[prop]).includes(val) : true
}

实际上,该函数可以使用return includesIfExists(myFilters.authors, "id", book.id) && ... ,这样您就不会重复两次。

.some()

答案 1 :(得分:0)

filter(books, (book) => {
    return myFilters.authors.map(a => a.id).includes(book.author_id) &&  
    myFilters.skus.map(a => a.id).includes(book.sku);  
    ....

您可以轻松检查真实性并执行您的表达(如果存在)。这称为Guard。如果它的计算结果不为true,则使用OR运算符会将其默认为true,以便您的 return 表达式可以继续进行。它与三元运算符非常相似。

考虑:

filter(books, (book) => {
  return 
    ( myFilters.authors && myFilters.authors.map(a => a.id).includes(book.author_id) || true ) &&
    ( myFilters.skus && myFilters.skus.map(a => a.id).includes(book.sku) || true );
    ...

可读性

您可能不希望这样做的原因有很多。主要原因可能是为了提高可读性和可维护性。您的代码简短明了;但是,从现在起5年(甚至2个月)内,您将能够快速知道如何对其进行修改或修复错误?还会有人吗?

为此,通常最好表现得更好:

filter(books, (book) => {
   let has_authors     = true       // default case if author filters not supplied
   let has_skus        = true       // default case if skus filters not supplied
   let {authors, skus} = myFilters  // destructuring assignment for code legibility

   if ( authors )
     has_authors = authors.map(a => a.id).includes(book.author_id)

   if ( skus )
     has_skus = skus.map(a => a.id).includes(book.sku)

  return has_authors && has_skus
}

当然,可以使用some来最大程度地减少迭代次数(一次循环而不是两次),并使用函数调用以减少语法,从而使其更加干燥,从而使其更加干燥:

filter(books, (book) => {
   let has_authors     = true       // default case if author filters not supplied
   let has_skus        = true       // default case if skus filters not supplied
   let {authors, skus} = myFilters  // destructuring assignment for code legibility

   if ( authors )
     has_authors = hasId( authors, book.author_id )

   if ( skus )
     has_skus = hasId( skus, book.sku )

  return has_authors && has_skus
}

function hasId( array, id ) {
  return array.some(v => v.id == id )
}

上述工作示例

setup() // create globals and functions


let filtered_books = filter(books, (book) => {
   let has_authors     = true       // default case if author filters not supplied
   let has_skus        = true       // default case if skus filters not supplied
   let {authors, skus} = myFilters  // destructuring assignment for code legibility

   if ( authors )
     has_authors = hasId( authors, book.author_id )

   if ( skus )
     has_skus = hasId( skus, book.sku )

  return has_authors && has_skus
})

function hasId( array, id ) {
  return array.some(v => v.id == id )
}

console.log(`filtered_books: `, filtered_books)
console.log(`from: `, books)





function setup(){

  window.myFilters = {
    // authors: [ { id: 7 } ],  // <-- uncomment to show a case where no authors match
    skus: [
      { id: 3 },
      { id: 5 }
    ]
  }
  window.books = [
    {author_id:4, sku: 2},
    {author_id:5, sku: 3}
  ]
  window.filter = function(array, callback){
    return array.filter(callback)
  }
}