使用参数的 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
JavaScript filter callback that uses arguments
提问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.slice
to get the blacklisted elements in array form.
您可以使用Array.prototype.slice
数组形式获取列入黑名单的元素。
Then use Array.prototype.indexOf
to see if a given element is in the array for the filter function.
然后用于Array.prototype.indexOf
查看给定元素是否在过滤器函数的数组中。
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.call
is used on Array.prototype.slice
with the this
scope argument of arguments
instead of directly calling arguments.slice
since arguments
isn't actually a "real" array.
请注意,Function.prototype.call
它Array.prototype.slice
与this
范围参数 of一起使用,arguments
而不是直接调用,arguments.slice
因为arguments
它实际上不是“真实”数组。
回答by Jonathan Lonowski
To try to explain the reasons the snippets didn't succeed:
尝试解释片段未成功的原因:
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
arguments
inside of the iterator (function(e) {...}
), the statement will comparee
against 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
arguments
outside 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; }); }
If you're not using strict mode, the value of
this
will 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, anew 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(); }
Or, you can try using strict mode, which allows
this
to hold a primitive value without boxing it.
每个函数都定义了自己的
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; }); }
如果您不使用严格模式,则的值
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(); }
或者,您可以尝试使用严格模式,它允许
this
保存原始值而不对其进行装箱。
回答by Alexei Levenkov
arguments
are 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)