【问题标题】:Why won't passing `''.trim()` straight to `[].map()`'s callback work?为什么不能将 `''.trim()` 直接传递给 `[].map()` 的回调工作?
【发布时间】:2012-03-07 10:07:24
【问题描述】:

我有一个字符串数组。我想修剪数组中的每个字符串。

我认为使用 [].map()''.trim() 会起作用...

[' a', ' b   ', 'c'].map(String.prototype.trim);

...但是我的控制台说...

TypeError: String.prototype.trim 在 null 或 undefined 上调用

jsFiddle.

我在数组中看不到任何 nullundefined 值。

String.prototype.trim()Array.prototype.map() 是在我用来测试的 Chrome 17 中定义的。

为什么这不起作用?我觉得我忽略了一些明显的事情。

我意识到我可以在其中循环或删除一个函数。然而,这不是这个问题的重点。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    trimString 原型上,这意味着它期望this 上下文是一个字符串,其中Array 上的map 方法提供当前数组项作为第一个参数,并且this 上下文是全局对象。

    【讨论】:

    • 没错!我知道这将是显而易见的。我的大脑今天不工作了。谢谢斯莱斯。
    • 那么为什么这不起作用呢? [' a', ' b ', 'c'].map(String.prototype.trim.apply); ... 为什么这在 map() 上下文之外起作用? String.prototype.trim(' a ')(请注意,它实际上没有工作 - 返回一个空字符串 - 但它也不会抛出错误。)
    • @nrabinowitz: applythis 不会绑定到String.prototype.trim - 它绑定到undefinednullwindow。 (这就是他们发明Function.bind()的原因。)
    • @minitech - 啊。知道了。谢谢!
    • 刚开始收到 Ryan 的评论有点慢,但我发现 this 很有帮助。
    【解决方案2】:

    这是因为 trim 没有被正确的 this 上下文调用。请记住,this 在 JS 中是动态绑定的。您必须创建一个包装器以传递给trim 以正确绑定this

    [' a', ' b   ', 'c'].map(function (str) {
      return str.trim();
    });
    

    【讨论】:

    • 感谢您的回答。我想我一直在使用 jQuery 的 $.trim() 太频繁了。
    • 这几乎是完美的,除了你在循环中创建函数。
    • @Mrchief:上面的代码没有这样做。如果你把我现有的代码扔进一个循环中……
    • 当您遍历数组时,您已经处于循环中。 :) 你认为 map 是如何实现的? es5.github.io/#x15.4.4.19
    • @Mrchief:这是实现地图的一种方式。另一种是通过递归。无论哪种情况,如何实现 map 都没有实际意义。在这种情况下,该函数只创建一次。然后将指向函数的指针传递给 map,并且 map 使用与它的工作相同的引用。
    【解决方案3】:

    @Slace 所说的是正确的解释。 @ThomasEding 的答案也有效,但它可能在循环中创建函数,即not a good thing to do

    另一种做法是(reference here):

    [' a', ' b   ', 'c'].map(Function.prototype.call, String.prototype.trim);  
    // gives ["a", "b", "c"]
    

    标准浏览器免责声明:这将适用于 Function.prototype.callString.prototype.trim 可以使用的任何地方,对于旧版浏览器,您可以轻松地将 trim 替换为 polyfill,如下所示:

    if(!String.prototype.trim) {  
      String.prototype.trim = function () {  
        return this.replace(/^\s+|\s+$/g,'');  
      };  
    }
    

    更新:有趣的是,虽然这在 Chrome 中运行得最快,但 @ThomasEding 的方法在 IE10 和 FF20 中运行得稍微快一些 - http://jsperf.com/native-trim-vs-regex-trim-vs-mixed

    【讨论】:

    • 我很确定@ThomasEdig 的回答不会创建多个函数。我假设map 函数接受一个函数引用,然后每次迭代调用它 一次。函数本身被创建一次,然后传递给 map 函数——就像jQuery 对map 的实现一样:james.padolsey.com/jquery/#v=1.7.2&fn=jQuery.map
    • 是的...从我的测试来看,这似乎是真的。我会改正的。
    【解决方案4】:

    使用 ES6 语法可以这么简单:

    [' hello  ', '  world'].map(str => str.trim());
    

    【讨论】:

    • 这是2017年最好的方式。让我们看看2018年会发生什么:D
    猜你喜欢
    • 1970-01-01
    • 2011-06-19
    • 2012-04-04
    • 1970-01-01
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多