Seek and Destory, question about how params are getting passed through

I had a question about this code snippet that I found as a solution to this challenge:

function destroyer(arr) {
    var args = Array.prototype.slice.call(arguments);
    args.splice(0,1);
  return arr.filter(function(element) {
    return args.indexOf(element) === -1;
  });
}

I realize that the var args lines was used to slice up the arguments in actual arrays. args.splice was used to isolate the array we want to look at from the criteria we want to filter by.

My question then is, how does the function in filter know to iterate through the elements, wouldn’t elements also be the arr param that was original passed through?

arr is the variable assigned to the first argument passed to the function destroyer. The reason that we need to use arguments is because the function definition fails to assign and subsequent arguments to variables.

I don’t think this answers my question unless I’m missing something here.

Let me explain what I think the code is doing and explicity where I am getting confused.

function destroyer(arr) {
// we are taking arguments and turning it into a proper array
var args = Array.prototype.slice.call(arguments);

// the first element of args is being spliced off, this is the array         
//that we want to check
args.splice(0,1);

// Asking to return arr filtered based on the call back function's
//criteria
  return arr.filter(function(element) {

//this is what the callback function is performing, what is getting 
//passed into element?
// Is 2 and then 3 being passed in them for element, are both 
//at being passed and its iterating through them?  
//How does it know to iterate through them?
    return args.indexOf(element) === -1;
  });
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);

filter() calls the callback function once for each element in an array. The callback is invoked with three arguments: the value, the index, and the Array object being traversed. In the code you provided only the first of the arguments, the value, is used by the callback. BUt you could write a function that deals with all three if you needed to.

1 Like

Right, so in the params listed, 2 and 3 are the values that will be passed into the callback function to check against the args array correct? How does the callback function know to pass in 2 and 3. Is it passing in those values on at a time? Is it passing in both and comparing? I guess I’m asking, what going on under the hood of the call back basically. How does that anonymous function know the correct values to pass in from the original params used when invoking destroyer?

I think the short answer is yes one at a time. :slight_smile:

I think the detailed under the hood answer(or at least a starting point) might be 22.1.3.7 of ECMAScript® 2015 Language Specification which spells out the Array.prototype.filter() method step by step including its handling of the callback function.

Ok, so how does it know to pass in 2 and 3. I know that it is since it passed the test, but HOW does it know to pass in 2 and 3, why doesn’t it pass in the [1, 2, 3, 1, 2, 3] array as well? How does it know to iterate through 2 and 3?

From the documentation page:

callbackfn is called with three arguments: the value of the element, the index of the element, and the object being traversed.

My question is, in the code snippet above, how did it know that the value to pass into callbackfn should be 2, and then 3, why not [1, 2, 3, 1, 2, 3], then 2 then 3 for instance? What is happening in that anonymous function that is just so happens to pull in the correct params, iterates through them if necessary, and then allows filer to work correctly on the target array, in this case args?

It’s actually iterating 1,2,3,1,2,3 one at a time…isn’t it? I added two console.log() statements to your annotated snippet and that seems to be the case.

https://jsfiddle.net/tdreid/tp79o76u

function destroyer(arr) {
// we are taking arguments and turning it into a proper array
var args = Array.prototype.slice.call(arguments);

// the first element of args is being spliced off, this is the array         
//that we want to check
args.splice(0,1);

// Asking to return arr filtered based on the call back function's
//criteria
  return arr.filter(function(element) {

//this is what the callback function is performing, what is getting 
//passed into element?
// Is 2 and then 3 being passed in them for element, are both 
//at being passed and its iterating through them?  
//How does it know to iterate through them?
    console.log(element);
    console.log("index in 'args' is "+args.indexOf(element))
    return args.indexOf(element) === -1;
  });
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);

/* Output 
1
index in 'args' is -1
2
index in 'args' is 0
3
index in 'args' is 1
1
index in 'args' is -1
2
index in 'args' is 0
3
 index in 'args' is 1
*/

Hey friend let me try to explain.

Destroyer waits only for one argument to be passed. Since we pass more then one argument it will assign only first one to “arr” and it will be array of numbers. But we still have the “arguments” object that has ALL the arguments passed, so we create an array “args” that will contain them.

  1. “args” - this variable will hold the array of arguments that were passed to the “destroyer” starting from 2nd argument (because we spliced the first argument which was an array of numbers);

  2. We use built-in Array method “filter” against the “arr” variable that is our array of numbers (first argument). Callback function in filter, will be passed with current iteration’s number in the array, for e.g.:

[1,2,3,4].filter(function(element) { return element === 3; }) - it will start from 1, but 1 != 3, go to 2 but !=3, then encounter 3 that === 3 and add it to the new filtered array and will go on until all numbers in the [1,2,3,4] array are covered.

So ho does it filter? You see [1,2,3,4].indexOf(2) returns the index of the first 2 that it encounters. The index of that 2 will be 1 (because start from 0). But if if .indexOf(item) won’t find this item in the array it return -1. Finally:

destroyer([1, 2, 3, 1, 2, 3], 2, 3);
arr = [1, 2, 3, 1, 2, 3];
args = [2, 3];

apply filter to "arr"
1 iteration - "do we have 1 in array “args”? returns -1 because we dont!
2 iteration - "do we have 2 in array “args”? returns index of 2 in args and it’s 1 (every number that is >0 is considered as "true) so it makes it’s way to the new filtered array;
3 iteration - "do we have 3 in array “args”? returns index of 3 in args and it’s 2 (every number that is >0 is considered as "true) so it makes it’s way to the new filtered array;
4 iteration - "do we have 1 in array “args”? returns -1 because we dont! so this 1 doesn’t make it’s way to the new filtered array.

Hope that explains the logic behind all that. For “Truthy, Falsy values” please read this paragraph - http://speakingjs.com/es5/ch10.html#truthy_falsy

Is the confusion re: how .filter() knows which argument is the array and which are the predicates? I added two console.log(args)s

function destroyer(arr) {
  
  var args = Array.prototype.slice.call(arguments);  // ALL arguments
  console.log(args);  // >> Array [ Array[6], 2, 3 ]

  args.splice(0, 1);  // Remove element [0], leaving predicates
  console.log(args);  // >> Array [ 2, 3 ]
  ...

OK that makes a lot sense thanks

Nice, that’s good to hear!