Javascript - 将trim函数应用于数组中的每个字符串

100

想要修剪数组中的每个字符串,例如给定:

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

输出

['aa', 'bb']

我的第一次尝试是

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

在Chromium中出现了"TypeError: Function.prototype.apply was called on undefined, which is a undefined and not a function"的错误。

然后我尝试了

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

它有效。有什么区别吗?

12个回答

149

或者可以使用箭头函数解决:

x.map(s => s.trim());

13
我建议:let trimedArr = oldArr.map(str => str.trim()); 的翻译是:将 oldArr 数组中的每个字符串都去除首尾空格,生成一个新的数组 trimedArr - Flame_Phoenix
@Dominic 我正在使用这个,但是当我压缩我的js时会出现错误。我正在使用https://javascript-minifier.com/网站来压缩js。 - Sachin Sarola
1
@SachinSarola 看起来这个压缩工具已经跟不上现代 JS 语法了。最好的方法是将 JS 构建和压缩作为构建流程的一部分,例如使用 webpack。 - Dominic
对我来说,x.map(s => return s.trim());有效,但上面的代码无效。 - rafagarci
@rafagarci 这是一个语法错误,你需要在return语句周围加上大括号。 - undefined

109
String.prototype.trim.apply 是一个未绑定到 trimFunction.prototype.apply方法。使用map时,它将字符串、索引和数组作为参数调用,并对于thisArg提供无意义的值(undefined),但是 apply 需要在函数上调用:
var apply = String.prototype.trim.apply;
apply.call(undefined, x[0], 0, x) // TypeError

您可以将trim函数作为call的上下文来传递:
[' aa ', ' bb '].map(Function.prototype.call, String.prototype.trim)
// ['aa', 'bb']

这里发生的是什么事情。
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

1
我理解了。我以为 fun 的含义与 function(x) { return fun(x); } 相同。 - neuront
这在IE8上不起作用:String.prototype.trim在IE8上无法工作。 - Sachin Kainth
2
@SachinKainth:这个问题不是关于trim的,OP假设它是可用的。如果你想在IE8中尝试这些片段,你显然需要shim trimmap - Bergi
1
这已经非常过时了,使用 ES6 语法,您可以更轻松地完成此操作: const newArray = oldArray.map(string => string.trim()) - svelandiag
1
@svelandiag,“apply”未绑定的解释以及如何使用“thisArgument”的说明仍然准确。当然,“arr.map(function(str) { return str.trim(); })”或“arr.map(str => str.trim())”一直更简单。 - Bergi

40

不需要依赖项的简单版本:

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

ES6变体:

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

ES6函数变体:

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

27
如果您正在使用JQuery,则更好的方法是这样做,因为它也适用于IE8(我需要支持IE8):

如果你正在使用jQuery,那么一个更好的方法来实现这个功能,同时也能在IE8上运行(我需要支持IE8)是这样的:

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

34
关键词是“如果”。 - gburning

18

首先,要简单执行:

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

那么,第一个不起作用的原因是字符串被传递为回调函数的参数,而不是上下文。由于您未传递任何参数给 apply,因此您会得到与以下代码相同的消息:

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

现在,纯属娱乐,假设您不满意map使用回调这种方式,并且您想通过上下文而不是参数来传递函数。

然后你可以这样做:

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"]

我说“基本上是为了好玩”,因为修改你不拥有的对象(这里是Array的原型)被广泛认为是一种不良实践。但是你也可以编写一个实用函数,将数组和回调作为参数传入。


你的意思是使用 String.prototype.trim.apply.call() 会得到相同的消息,对吗? - Butt4cak3

5

我刚刚比较了一些裁剪字符串数组的方法,以获得最短和最快的方法。有兴趣的人可以参考这个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);

注意: jQuery只是用来比较需要输入的字符数的;)

3

受Bergi完美回答的影响,我只想补充一点,对于那些不需要传入 this 参数的方法,您可以按照以下方式完成相同的工作;

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

工作得非常好! - Sanjay

3
保持简单和愚蠢:

代码

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

输出

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

1
为什么要重复一年前已经给出的答案呢? - Forage

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"]

所有主流浏览器都支持 forEach(),但请注意,IE 仅从版本9开始支持。


1

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

console.log(x)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接