使用参数的 JavaScript 过滤器回调

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33686942/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 16:48:14  来源:igfitidea点击:

JavaScript filter callback that uses arguments

javascript

提问by dot

The goal is to filter an array and remove all occurrences of elements specified in its argument list.

目标是过滤数组并删除其参数列表中指定的所有元素。

For example, given removeElements([1, 2, 3, 1, 2, 3,4], 2, 3), my output should be [1,1,4].

例如,给定 removeElements([1, 2, 3, 1, 2, 3,4], 2, 3),我的输出应该是 [1,1,4]。

function removeElements(arr) {
//I got an error that says **functions** not allowed **inside loop**
  for(var i=1;i<arguments.length;i++){
    arr= arr.filter(function(e){
        return e!==arguments[i];
    });
  }
  return arr;
}

Second thing I tried is moving the filter out of the for loop.

我尝试的第二件事是将过滤器移出 for 循环。

function removeElements(arr) {
  function isNotEqual(e){
    return e!==this;
  }
  for(var i=1;i<arguments.length;i++){
    arr= arr.filter(isNotEqual,arguments[i]);
  }
  return arr;
}

None of them work. It always return arr as [1,2,3,1,2,3,4]. Can you please tell as to what is wrong in my usage? Or what is the approach for using filter in this scenario?

他们都没有工作。它总是将 arr 返回为 [1,2,3,1,2,3,4]。你能告诉我我的用法有什么问题吗?或者在这种情况下使用过滤器的方法是什么?

回答by arcyqwerty

You can use Array.prototype.sliceto get the blacklisted elements in array form.

您可以使用Array.prototype.slice数组形式获取列入黑名单的元素。

Then use Array.prototype.indexOfto see if a given element is in the array for the filter function.

然后用于Array.prototype.indexOf查看给定元素是否在过滤器函数的数组中。

http://jsfiddle.net/Loothof7/

http://jsfiddle.net/Loothof7/

function removeElements(arr) {
  var blacklist = Array.prototype.slice.call(arguments, 1);
  return arr.filter(function(e) {
    return blacklist.indexOf(e) == -1;
  });
}

alert(removeElements([1, 2, 3, 1, 2, 3,4], 2, 3));

Note that Function.prototype.callis used on Array.prototype.slicewith the thisscope argument of argumentsinstead of directly calling arguments.slicesince argumentsisn't actually a "real" array.

请注意,Function.prototype.callArray.prototype.slicethis范围参数 of一起使用,arguments而不是直接调用,arguments.slice因为arguments它实际上不是“真实”数组。

回答by Jonathan Lonowski

To try to explain the reasons the snippets didn't succeed:

尝试解释片段未成功的原因:

  1. Every function defines its own arguments, even when the function is embedded.

    function removeElements(arr) {
        console.log(arguments);
        // Arguments {
        //   0: Array [1, 2, 3, 1, 2, 3, 4],
        //   1: 2,
        //   2: 3
        // }
    
        arr = arr.filter(function (e) {
            console.log(arguments);
            // Arguments {
            //   0: 1, 2, 3, 1, ...             (each value in `arr`)
            //   1: 0, 1, 2, 3, ...             (each index)
            //   2: Array [1, 2, 3, 1, 2, 3, 4] (`arr` itself)
            // }
    
            // ...
        });
    
        return arr;
    }
    
    removeElements([1, 2, 3, 1, 2, 3, 4], 2, 3);
    

    By retrieving values from argumentsinside of the iterator (function(e) {...}), the statement will compare eagainst values in the 2nd Arguments.

    for(var i=1;i<arguments.length;i++){
        arr = arr.filter(function(e){
            // 1st = 0              (the first index from `arr`)
            // 2nd = [1, 2, 3, ...] (the `arr` itself)
            console.log(arguments[i]);
    
            return e!==arguments[i];
        });
    }
    

    One option to resolve this is to access argumentsoutside of the iterator function, stashing the value in a variable that won't have the same conflict:

    for(var i=1;i<arguments.length;i++){
        var skip = arguments[i];
        arr = arr.filter(function (e) {
            return e !== skip;
        });
    }
    

    http://jsfiddle.net/y7evq6nq/

  2. If you're not using strict mode, the value of thiswill always be an Object.

    When you provide a primitive value for a thisArg, it will be boxed into its equivalent Object type. In this case, a new Number.

    function foo() {
        console.log(typeof this, this); // 'object' Number(3)
        return true;
    }
    
    [0].filter(foo, 3);
    

    And, since ===first checks for type equality, a primitive and boxed number cannot be equal:

    var number = 3;
    var boxedNumber = new Number(3);
    
    console.log(typeof number);      // 'number'
    console.log(typeof boxedNumber); // 'object'
    
    console.log(typeof number === typeof boxedNumber); // false
    console.log(number === boxedNumber);               // false
    

    You can use the .valueOf()method to retrieve the primitive value from the object.

    function isNotEqual(e){
      return e!==this.valueOf();
    }
    

    http://jsfiddle.net/ow9b78bf/

    Or, you can try using strict mode, which allows thisto hold a primitive value without boxing it.

  1. 每个函数都定义了自己的arguments,即使该函数是嵌入的。

    function removeElements(arr) {
        console.log(arguments);
        // Arguments {
        //   0: Array [1, 2, 3, 1, 2, 3, 4],
        //   1: 2,
        //   2: 3
        // }
    
        arr = arr.filter(function (e) {
            console.log(arguments);
            // Arguments {
            //   0: 1, 2, 3, 1, ...             (each value in `arr`)
            //   1: 0, 1, 2, 3, ...             (each index)
            //   2: Array [1, 2, 3, 1, 2, 3, 4] (`arr` itself)
            // }
    
            // ...
        });
    
        return arr;
    }
    
    removeElements([1, 2, 3, 1, 2, 3, 4], 2, 3);
    

    通过从arguments迭代器 ( function(e) {...})内部检索值,该语句将e与第二个参数中的值进行比较。

    for(var i=1;i<arguments.length;i++){
        arr = arr.filter(function(e){
            // 1st = 0              (the first index from `arr`)
            // 2nd = [1, 2, 3, ...] (the `arr` itself)
            console.log(arguments[i]);
    
            return e!==arguments[i];
        });
    }
    

    解决此问题的一种选择是arguments在迭代器函数之外访问,将值存储在不会有相同冲突的变量中:

    for(var i=1;i<arguments.length;i++){
        var skip = arguments[i];
        arr = arr.filter(function (e) {
            return e !== skip;
        });
    }
    

    http://jsfiddle.net/y7evq6nq/

  2. 如果您不使用严格模式,则的值this将始终是一个对象。

    当您为 a 提供原始值时thisArg,它将被装箱到其等效的 Object 类型中。在这种情况下,一个new Number.

    function foo() {
        console.log(typeof this, this); // 'object' Number(3)
        return true;
    }
    
    [0].filter(foo, 3);
    

    而且,由于===首先检查类型相等,原始数和装箱数不能相等:

    var number = 3;
    var boxedNumber = new Number(3);
    
    console.log(typeof number);      // 'number'
    console.log(typeof boxedNumber); // 'object'
    
    console.log(typeof number === typeof boxedNumber); // false
    console.log(number === boxedNumber);               // false
    

    您可以使用该.valueOf()方法从对象中检索原始值。

    function isNotEqual(e){
      return e!==this.valueOf();
    }
    

    http://jsfiddle.net/ow9b78bf/

    或者,您可以尝试使用严格模式,它允许this保存原始值而不对其进行装箱。

回答by Alexei Levenkov

argumentsare function specific pseudo-variable. Using it inside callback will give arguments of callback and not outer function.

arguments是函数特定的伪变量。在回调中使用它会给出回调参数而不是外部函数。

function removeElements(arr) {
  var args = Array.prototype.slice.call(arguments);
  for(var i=1;i<args.length;i++){
    arr= arr.filter(function(e){
        return e!==args[i];
    });
  }
}

回答by Azad

I have already answered this type of question hereany way I post it to you

我已经在这里回答了这种类型的问题我可以将其发布给您

A simple function

一个简单的函数

function filter(){
    var j = -1; 
    for(var i = 1; i < arguments.length; i++){
        j = arguments[0].indexOf(arguments[i]);
        if(j > -1){
           arguments[0].splice(j, 1);
        }
    }
    return arguments[0];
}

you can call this function with no of args eg:

您可以在没有参数的情况下调用此函数,例如:

 filter([1,2,3,4,5,6,7,8,9], 1, 3, 5); //return [2,4,6,7,8,9]
 filter([1,2,3,4,5,6,7,8,9], 1); //return [2,3,4,5,6,7,8,9]

回答by David Gomez

I think this is what you want to do, maybe I'm wrong.

我想这就是你想要做的,也许我错了。

var result = [1, 2, 3, 1, 2, 3, 4].filter(function(item) {
  return item !== 1 && item !== 2;
});

console.log(result); // [3, 3, 4]

UPDATE:

更新:

This function can do the job you want passing the items to be remove as an array instead of turning the arguments[1]param an Arrayusing slice.call():

此函数可以完成您希望将要删除的项目作为数组传递的工作,而不是使用以下方法将arguments[1]参数转换为数组slice.call()

function removeItems(arr, items) {
  return arr.filter(function (elem) {
    return items.indexOf(elem) === -1;
  });
}

var result = removeItems([1, 2, 3, 1, 2, 3, 4], [2, 3]);

console.log(result); // [1, 1, 4]

回答by MHernandez

There are really good answers here, but you can do it very clean in this way, remember you have an objects option in filter method which you can use in the callback function, in this case i'm using it like : arguments[i] so I can check every value in the arguments array

这里有非常好的答案,但是您可以通过这种方式做得非常干净,请记住,过滤器方法中有一个对象选项,您可以在回调函数中使用它,在这种情况下,我使用它:arguments[i]所以我可以检查参数数组中的每个值

function destroyer(arr) {

   for(var i = 1; i < arguments.length; i++){
     arr = arr.filter(isIn, arguments[i]);
   } 

  function isIn(element,index, array){
     if (element != this){
        return element;
     }
  }  

  return arr;
}

回答by STR.split

This will use a callback function to check against the two numbers given in the arguments list.

这将使用回调函数来检查参数列表中给出的两个数字。

function removeElements(arr, num1, num2){
  return arr.filter(numChecks(num1, num2));
  
}
function numChecks(num1, num2){
  return function(element){
    return element !== num1 && element !== num2;
  }
}
removeElements([1, 2, 3, 1, 2, 3,4], 2, 3)