【问题标题】:How do I pass an extra parameter to the callback function in Javascript .filter() method?如何在 Javascript .filter() 方法中将额外参数传递给回调函数?
【发布时间】:2011-12-07 05:41:57
【问题描述】:

我想将数组中的每个字符串与给定的字符串进行比较。我目前的实现是:

function startsWith(element) {
    return element.indexOf(wordToCompare) === 0;
}
addressBook.filter(startsWith);

这个简单的函数有效,但只是因为现在 wordToCompare 被设置为全局变量,但我当然想避免这种情况并将其作为参数传递。我的问题是我不确定如何定义 startsWith() 所以它接受一个额外的参数,因为我真的不明白它采用的默认参数是如何传递的。我已经尝试了所有我能想到的不同方法,但都没有奏效。

如果您还可以解释传递给“内置”回调函数的参数(对不起,我不知道更好的术语)是如何工作的,那就太好了

【问题讨论】:

标签: javascript callback scope


【解决方案1】:
function startsWith(element, wordToCompare) {
    return element.indexOf(wordToCompare) === 0;
}

// ...
var word = "SOMETHING";

addressBook.filter(function(element){
    return startsWith(element, word);
});

【讨论】:

    【解决方案2】:

    使startsWith 接受要比较的单词并返回一个函数,然后将其用作过滤器/回调函数:

    function startsWith(wordToCompare) {
        return function(element) {
            return element.indexOf(wordToCompare) === 0;
        }
    }
    
    addressBook.filter(startsWith(wordToCompare));
    

    另一种选择是使用Function.prototype.bind [MDN](仅在支持 ECMAScript 5 的浏览器中可用,请点击旧版浏览器的 shim 链接)并“修复”第一个参数:

    function startsWith(wordToCompare, element) {
        return element.indexOf(wordToCompare) === 0;
    }
    
    addressBook.filter(startsWith.bind(this, wordToCompare));
    

    我不太明白它采用的默认参数是如何传递的

    没有什么特别之处。在某些时候,filter 只是调用回调并传递数组的当前元素。所以它是一个调用另一个函数的函数,在这种情况下是你作为参数传递的回调。

    下面是一个类似函数的例子:

    function filter(array, callback) {
        var result = [];
        for(var i = 0, l = array.length; i < l; i++) {
            if(callback(array[i])) {  // here callback is called with the current element
                result.push(array[i]);
            }
        }
        return result;
    }
    

    【讨论】:

    • 好的,我明白了。我试图将参数直接传递给回调函数......我真的需要处理我的 JavaScript。谢谢菲利克斯,你的回答很有帮助
    • 传递额外的参数怎么样?我尝试传递一系列参数,但似乎失败了
    • @geotheory:他们呢?你可以像其他函数一样传递多个参数。
    • bind(this) after function name 以及 filter() 链接帮助我在函数内部使用 .this。谢谢。
    • 在第一个 sn-p 中,element 来自哪里,在 startsWith 函数中?
    【解决方案3】:

    filter的第二个参数会在回调中设置this

    arr.filter(callback[, thisArg])
    

    所以你可以这样做:

    function startsWith(element) {
        return element.indexOf(this) === 0;
    }
    addressBook.filter(startsWith, wordToCompare);
    

    【讨论】:

    • 我发现这是最好的答案。
    • 所以现在新数组将被分配给 wordToCompare 对象,对吧?以后如何使用 wordToCompare 对象访问新数组?
    • 最佳答案。非常适合过滤和查找。并且两者都符合 WC3 文档:thisValue - 可选。要传递给函数以用作其“this”值的值。如果此参数为空,则值“undefined”将作为其“this”值传递
    • @TarekEldeeb 只需传递您制作的对象{one: 'haha', two:'hoho'}
    • 这是一个很好的例子,说明在复杂性、复杂程度与简单程度方面的答案之间存在巨大差异
    【解决方案4】:

    您可以在过滤器中使用箭头函数,如下所示:

    result = addressBook.filter(element => element.indexOf(wordToCompare) === 0);
    

    Arrow functions on MDN

    与函数表达式相比,箭头函数表达式的语法更短,并且在词法上绑定 this 值(不绑定自己的 this、arguments、super 或 new.target)。箭头函数始终是匿名的。这些函数表达式最适合非方法函数,它们不能用作构造函数。

    【讨论】:

    • 注:IE 不支持
    【解决方案5】:

    基于oddRaven 的回答 和 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

    我做了 2 种不同的方式。 1)使用函数方式。 2)使用内联方式。

    //Here  is sample codes : 
    
    var templateList   = [
    { name: "name1", index: 1, dimension: 1 }  ,
    { name: "name2", index: 2, dimension: 1 }  ,
    { name: "name3", index: 3, dimension: 2 }  ];
    
    
    //Method 1) using function : 
    
    function getDimension1(obj) {
                    if (obj.dimension === 1) // This is hardcoded . 
                        return true;
                    else return false;
                } 
    
    var tl = templateList.filter(getDimension1); // it will return 2 results. 1st and 2nd objects. 
    console.log(tl) ;
    
    //Method 2) using inline way 
    var tl3 = templateList.filter(element => element.index === 1 || element.dimension === 2  ); 
    // it will return 1st and 3rd objects 
    console.log(tl3) ;

    【讨论】:

      【解决方案6】:

      对于那些使用箭头函数寻找 ES6 替代方案的人,您可以执行以下操作。

      let startsWith = wordToCompare => (element, index, array) => {
        return element.indexOf(wordToCompare) === 0;
      }
      
      // where word would be your argument
      let result = addressBook.filter(startsWith("word"));
      

      使用includes的更新版本:

      const startsWith = wordToCompare => (element, index, array) => {
        return element.includes(wordToCompare);
      }
      

      【讨论】:

      • 有什么方法可以从元素、索引和数组中传递不同的参数?例如,我想传递一个 X 变量。
      • @leandrotk 在这种情况下,“wordToCompare”是要传入的“X”变量。
      【解决方案7】:

      对于任何想知道为什么他们的胖箭头函数忽略 [, thisArg] 的人,例如为什么

      ["DOG", "CAT", "DOG"].filter(animal =&gt; animal === this, "DOG") 返回[]

      这是因为 this 在这些箭头函数中是在创建函数时绑定的,并且在更广泛的包含范围内设置为 this 的值,因此 thisArg 参数被忽略。通过在父作用域中声明一个新变量,我很容易解决这个问题:

      let bestPet = "DOG"; ["DOG", "CAT", "DOG"].filter(animal => animal === bestPet); => ["DOG", "DOG"]

      这里是更多阅读的链接: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this

      【讨论】:

        【解决方案8】:

        有一种使用过滤器功能的简单方法,可以访问所有参数,而且不会过于复杂。

        除非回调的 thisArg 设置为另一个范围过滤器不会创建自己的范围,我们可以访问当前范围内的参数。我们可以设置“this”来定义不同的范围,以便在需要时访问其他值,但默认情况下它设置为调用它的范围。您可以看到 this 用于 Angular 作用域in this stack

        使用 indexOf 违背了过滤器的目的,并增加了更多开销。过滤器已经在遍历数组了,为什么还要再遍历一遍呢?我们可以改为简单的pure function

        这是一个 React 类方法中的用例场景,其中状态有一个名为 items 的数组,通过使用过滤器我们可以检查现有状态:

        checkList = (item) => {  // we can access this param and globals within filter
          var result = this.state.filter(value => value === item); // returns array of matching items
        
          result.length ? return `${item} exists` : this.setState({
            items: items.push(item) // bad practice, but to keep it light
          });
        }
        

        【讨论】:

          猜你喜欢
          • 2017-04-09
          • 1970-01-01
          • 2012-01-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多