使用参数的JavaScript过滤器回调

时间:2015-11-13 06:15:06

标签: javascript

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

例如,给定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;
}

我尝试的第二件事是将过滤器移出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;
}

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

7 个答案:

答案 0 :(得分:9)

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

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

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));

请注意Function.prototype.call使用Array.prototype.slice this范围arguments范围,而不是直接调用arguments.slice,因为arguments isn&# 39;实际上是一个真实的&#34;阵列。

答案 1 :(得分:3)

试图解释片段没有成功的原因:

  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. 如果您未使用strict mode,则this的值将始终为对象。

    当您为thisArg提供原始值时,它将被装入其等效的对象类型中。在这种情况下,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保持原始值而不用装箱。

答案 2 :(得分:2)

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];
    });
  }
}

答案 3 :(得分:1)

我已经回复了这类问题here,无论我发布给你什么

一个简单的功能

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];
}

你可以在没有args的情况下调用这个函数,例如:

 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]

答案 4 :(得分:0)

我认为这就是你想做的事,也许我错了。

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

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

<强>更新

此功能可以完成您想要将要删除的项目作为数组传递的作业,而不是使用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]

答案 5 :(得分:0)

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

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;
}

答案 6 :(得分:0)

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

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)