I have a function to filter CSS classes for duplicates and empty spaces, but my function exports arrays with empty spaces anyway...
var classes = function (className, current) {
var classNames = [className], uniques = {};
if(current) classNames = classNames.concat(current.split(' '));
return classNames.filter(function (className,i) {
if(className == "") return;
className = className.match(/\S+/)[0];
if (!uniques[className]) return uniques[className] = className;
});
};
When I run classes(' foo') I get [" foo"] with a empty space anyway,
although console.log(' foo'.match(/\S+/)[0]; returns 'foo' with no space.
What am I missing?
1 Answer 1
You misunderstand how filter works. From the fine manual:
The
filter()method creates a new array with all elements that pass the test implemented by the provided function.
The return value from the callback tells filter which elements of classNames should be passed through, the return value is merely tested for truthiness. The return value of the callback isn't returned by filter, the original untouched values in classNames are. So the problem isn't that an extra space is being added, the problem is that nothing is removing the spaces.
If you want to test and modify at the same time then reduce will serve you better:
return classNames.reduce(function(a, className) {
if(!className)
return a;
className = className.match(/\S+/)[0];
if(!uniques[className]) {
a.push(className);
uniques[className] = className;
}
return a;
}, []);
Note all the return a; statements and the lack of return;s.
Demo: http://jsfiddle.net/ambiguous/bw3JS/
You could also use map to clean up the spaces and then filter to clean up the undefineds with something like this:
return classNames.map(function(className) {
if(!className)
return;
className = className.match(/\S+/)[0];
if(!uniques[className])
return uniques[className] = className;
}).filter(function(className) {
return typeof className !== 'undefined';
});
3 Comments
.filter() which is poinless. Good catch and thanks for a alternative solution!.map() also be a solution here. (?)map but each return value from the map callback ends up in the final array. map would leave you with undefined values or empty strings or some other value that you'd need a separate filter pass to clean up: jsfiddle.net/ambiguous/8j5Bb
' foo'into this function and get back a clean['foo']with no spaces. And I think I did everything correct but somewhere a empty space is being added and I can't find where...