admin管理员组

文章数量:1313121

I'm trying to get the hang of callback functions but I've ran into something that I don't fully understand.

This block of code works great when it's used in the example below.

zombieCreatures = creatures.filter(filterCreatures);

Unfortunately this block of code doesn't work when it's used in the same example.

zombieCreatures = creatures.filter(function(v) {
    filterCreatures(v);
});

To me they look like identical instructions but obviously I am incorrect. What is the difference? Is it possible to make a callback function call another function inside of .filter()?

'use strict';

var creatures = [], zombieCreatures = [];

var filterCreatures;

creatures = [
  {species: 'Zombie', hitPoints: 90},
  {species: 'Orc', hitPoints: 40},
  {species: 'Skeleton', hitPoints: 15},
  {species: 'Zombie', hitPoints: 85}
];
	
filterCreatures = function(v) {
  return v.species === 'Zombie';
}
	
zombieCreatures = creatures.filter(function(v) {
  filterCreatures(v);
});

console.log(zombieCreatures);

I'm trying to get the hang of callback functions but I've ran into something that I don't fully understand.

This block of code works great when it's used in the example below.

zombieCreatures = creatures.filter(filterCreatures);

Unfortunately this block of code doesn't work when it's used in the same example.

zombieCreatures = creatures.filter(function(v) {
    filterCreatures(v);
});

To me they look like identical instructions but obviously I am incorrect. What is the difference? Is it possible to make a callback function call another function inside of .filter()?

'use strict';

var creatures = [], zombieCreatures = [];

var filterCreatures;

creatures = [
  {species: 'Zombie', hitPoints: 90},
  {species: 'Orc', hitPoints: 40},
  {species: 'Skeleton', hitPoints: 15},
  {species: 'Zombie', hitPoints: 85}
];
	
filterCreatures = function(v) {
  return v.species === 'Zombie';
}
	
zombieCreatures = creatures.filter(function(v) {
  filterCreatures(v);
});

console.log(zombieCreatures);

Share Improve this question asked Nov 25, 2017 at 21:45 DR01DDR01D 1,36515 silver badges40 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

Yes, you can certainly call any other functions inside a filter callback.

The only thing you're missing is that the callback needs to return a value. Your callback doesn't have a return statement. It calls the filterCreatures() function, but then it discards the value returned by that function and by default returns undefined.

Compare with the original version of your code:

creatures.filter(filterCreatures);

In this code, filter() calls the filterCreatures function directly and then uses its return value to decide whether to include the element. You don't see this explicitly in the code, but filter() is looking for that return value.

Here's an exercise to help clarify this. Take your broken code and move the inline filter callback out to a named function. We'll call it filterCreaturesWrapper. So instead of this:

filterCreatures = function(v) {
  return v.species === 'Zombie';
}

zombieCreatures = creatures.filter(function(v) {
  filterCreatures(v);
});

we have this:

filterCreatures = function(v) {
  return v.species === 'Zombie';
}

filterCreaturesWrapper = function(v) {
  filterCreatures(v);
}

zombieCreatures = creatures.filter(filterCreaturesWrapper);

If you study that, you'll see it's exactly the same code as before, we just moved it around a little. filterCreaturesWrapper is the same function that was inline inside the .filter() call. And now the problem should jump out at us: filterCreatures has a return statement and filterCreaturesWrapper doesn't.

Going back to the original broken code, it's as if we had written:

zombieCreatures = creatures.filter(function(v) {
  filterCreatures(v);
  return undefined;  // .filter treats this as 'false'
});

So just add a return in your callback and it works:

'use strict';

var creatures = [], zombieCreatures = [];

var filterCreatures;

creatures = [
  {species: 'Zombie', hitPoints: 90},
  {species: 'Orc', hitPoints: 40},
  {species: 'Skeleton', hitPoints: 15},
  {species: 'Zombie', hitPoints: 85}
];
	
filterCreatures = function(v) {
  return v.species === 'Zombie';
}
	
zombieCreatures = creatures.filter(function(v) {
  return filterCreatures(v);  // <-- added "return"
});

console.log(zombieCreatures);

Not every language works like this. Ruby, for example, returns the last expression in a method (function) whether you explicitly say return or not. So if you were writing Ruby code (assuming all the other bits were converted to Ruby too), your code would have worked!

filter will call the function it was given for every item in the array. It will check the return value of that function for every item and if the return value is truthy, it will add that item in a new array.

On other words, it returns an array of all items for which the callback returns a truthy value.

In the first example, you are passing the filterCreatures function directly, which returns true when the creature is a zombie.

In the second example, you're passing another function and calling filterCreatures internally, but not returning anything meaning the callback passed to filter returns undefined for every item, which is falsy and nothing gets filtered.

For it to work, you must return the result of calling filterCreatures:

zombieCreatures = creatures.filter(function(v) {
    return filterCreatures(v);
});

That being said, adding the additional function around filterCreatures doesn't have much use when filterCreatures itself does everything you need.

本文标签: javascriptIn filter() how do I make a callback function call another functionStack Overflow