105

Want to trim each string in an array, e.g., given

x = [' aa ', ' bb '];

output

['aa', 'bb']

My first trial is

x.map(String.prototype.trim.apply)

It got "TypeError: Function.prototype.apply was called on undefined, which is a undefined and not a function" in chromium.

Then I tried

x.map(function(s) { return String.prototype.trim.apply(s); });

It works. What's the difference?

12 Answers 12

156

Or this can be solved with arrow functions:

trimmed_x = x.map(s => s.trim());
Sign up to request clarification or add additional context in comments.

5 Comments

I suggest: let trimedArr = oldArr.map(str => str.trim());
@Dominic I am using this but when I minify my js that time it will give the error I am using javascript-minifier.com site for minify js
@SachinSarola looks like that minifier is out of date with modern JS syntax. It's better to build and minify your JS as part of a build pipeline anyway using e.g. webpack
For me, x.map(s => return s.trim()); worked but the above did not.
@rafagarci that's a syntax error, you'd need braces around the return statement
109

String.prototype.trim.apply is the Function.prototype.apply method without being bound to trim. map will invoke it with the string, the index and the array as arguments and nothing (undefined) for the thisArg - however, apply expects to be called on functions:

var apply = String.prototype.trim.apply;
apply.call(undefined, x[0], 0, x) // TypeError

What you can do is passing the trim function as the context for call:

[' aa ', ' bb '].map(Function.prototype.call, String.prototype.trim)
// ['aa', 'bb']

What happens here is

var call = Function.prototype.call,
    trim = String.prototype.trim;
call.call(trim, x[0], 0, x) ≡
      trim.call(x[0], 0, x) ≡
            x[0].trim(0, x); // the arguments don't matter to trim

5 Comments

I see. I thought that fun would have the same meaning with function(x) { return fun(x); }.
This won't work on IE8: String.prototype.trim doesn't work with IE8.
@SachinKainth: The question is not about trim, OP assumes that it is available. If you want to try out the snippets in IE8, you obviously will need to shim trim and map.
This is very outdated with ES6 syntax you can do this much easier: const newArray = oldArray.map(string => string.trim())
@svelandiag The explanation why apply isn't bound, and how to use the thisArgument, is still accurate. Of course, arr.map(function(str) { return str.trim(); }) or arr.map(str => str.trim()) has always been simpler.
41

The simple variant without dependencies:

 for (var i = 0; i < array.length; i++) {
     array[i] = array[i].trim()
 }

ES6 variant:

const newArray = oldArray.map(string => string.trim())

ES6 function variant:

const trimmedArray = array => array.map(string => string.trim())

Comments

28

If you are using JQuery, then a better way to do this, as it will work with IE8 as well (I need to support IE8) is this:

$.map([' aa ', ' bb ', '   cc '], $.trim);

1 Comment

@DenysSéguret "If" is the keyword here.
19

First, do it simply :

x.map(function(s) { return s.trim() });

Then, the reason why the first one doesn't work is that the string is passed as argument to the callback, not as context. As you pass no argument to apply, you get the same message you would have got with

var f = String.prototype.trim.apply; f.call();

Now, mostly for fun, let's suppose you're not happy with the fact that map use the callback this way and you'd want to be able to pass a function using the context, not the argument.

Then you could do this :

Object.defineProperty(Array.prototype, "maprec", {
  value: function(cb){
      return this.map(function(v){ return cb.call(v) })
  }
});
console.log([' aa ', ' bb '].maprec(String.prototype.trim)); // logs ["aa", "bb"]

I said "mostly for fun" because modifying objects you don't own (Array's prototype here) is widely seen as a bad practice. But you could also make a utilitarian function taking both the array and the callback as arguments.

1 Comment

You mean the same message you would have got with String.prototype.trim.apply.call(), don't you?
5

I just compared some ways to trim an array of strings to get the shortest and fastest method. Who is interested in, here is a performance test on jsperf: http://jsperf.com/trim-array-of-strings

var chunks = "  .root  ,  .parent  >  .child  ".split(',')
var trimmed1 = chunks.map(Function.prototype.call, String.prototype.trim);
var trimmed2 = chunks.map(function (str) { return str.trim(); });
var trimmed3 = chunks.map(str => str.trim());
var trimmed4 = $.map(chunks, $.trim);

Note: jQuery is just here to compare the number of characters to type ;)

Comments

3

Influencing from Bergi's perfect answer, i just would like to add, for those methods which won't take a this argument, you may achieve the same job as follows;

var x = [' aa ', ' bb '],
    y = x.map(Function.prototype.call.bind(String.prototype.trim))

1 Comment

Worked really well!
3

Keep it simple and stupid:

Code

[' aa ', ' b b ', '   c c '].map(i=>i.trim());

Output

["aa", "b b", "c c"]

1 Comment

Why repeat an answer already given one year earlier?
1
var x = [" aa ", " bb "];
console.log(x); // => [" aa ", " bb "]

// remove whitespaces from both sides of each value in the array
x.forEach(function(value, index){
  x[index] = value.trim();
});

console.log(x); // => ["aa", "bb"]

All major browsers support forEach(), but note that IE supports it only beginning from version 9.

Comments

1

x = [' aa ', ' bb ', 'cccc '].toString().replace(/\s*\,\s*/g, ",").trim().split(",");

console.log(x)

Comments

-2

Another ES6 alternative

const row_arr = ['a ', ' b' , ' c ', 'd'];
const trimed_arr = row_arr.map(str => str.trim());
console.log(trimed_arr); // <== ['a', 'b', 'c', 'd']

3 Comments

array_map is not a native JS function and not defined here. => does not work.
@Greg the first version of this answer included an unspecified array_map() method
@musemind My mistake -- I should have looked at edits
-3
    ### Code
    <!-- language: lang-js -->

     var x=  [' aa ', ' b b ', '   c c ']
var x = x.split(",");
            x = x.map(function (el) {
                return el.trim();
                console.log(x)

    ### Output
    <!-- language: lang-none -->
        ["aa", "b b", "c c"]     

4 Comments

Please put your answer always in context instead of just pasting code. See here for more details.
Are you sure about that? When trying to use your code, the following error is thrown: TypeError: x.split is not a function
### Try once this code.... var x= [' aa ', ' b b ', ' c c '] var x = x.split(","); x = x.map(function (el) { return el.trim(); console.log(x)
### TRY var x = x.split(","); x = x.map(function (el) { return el.trim(); console.log(x)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.