【问题标题】:In Javascript, why does array.map(String) return array of strings?在 Javascript 中,为什么 array.map(String) 返回字符串数组?
【发布时间】:2013-05-02 02:25:07
【问题描述】:

数组对象上的列表处理例程map 有时非常方便。这是使用它的一种方便方法:

var numarr = [1,2,3,4];
console.log(numarr.map(String))

>>> ["1", "2", "3", "4"]

到目前为止,我认为这是理所当然的。然而,今天我对此感到困惑。 map 函数上面返回的是一个字符串数组。我们通常将一个函数作为参数传递给map。在上述情况下,我们传递 String 对象。 String是在Javascript实现里面实现的,所以不知道有什么特长。上面的代码就像是为数组中的每个项目创建了一个 Stringnew 实例。

如果不清楚,请考虑一下。如果我决定在 Javascript 中实现一个对象,比如 MyString 并将其传递给 map,我将不会得到上述行为。

function MyString(x) { this.val = x; }

MyString.prototype.toString = function () { return String(this.val); };

var ms = new MyString(4)

console.log(String(ms));
>>> "4"

var arr = [1,2,3];
arr.map(MyString)
>>> [undefined, undefined, undefined]

有谁知道为什么 arr.map(String) 会这样工作?

更新:A comment I added below 更好地阐明了我的问题。

【问题讨论】:

  • 你看到typeof String返回什么了吗? “如果我决定在 Javascript 中实现一个对象,请说 MyString [...]”MyString 也是一个函数!但它显示undefined,因为你没有从它返回任何东西。
  • 你说得对,我什么都不退。但那我应该返回什么? MyString 的新实例?
  • 这里重要的一点是,虽然String 是一个构造函数,当它被new 调用时,它返回一个字符串object,它返回一个字符串原始值,当它被称为没有 new。如果你愿意,你可以对你的函数做类似的事情。但总的来说,这对于自定义构造函数没有意义,因此您宁愿将 .maparr.map(function(v) { return new MyString(v); }); 一起使用。

标签: javascript functional-programming


【解决方案1】:

Array.map 返回一个数组,其元素是通过将指定函数应用于this 数组中的每个值而返回的值。 String is a function; it returns a string. 仅此而已。

【讨论】:

  • 函数始终是一流的 Javascript 对象:函数就是函数对象。您还可以在其他 javascript“类型”上运行相同的技巧:数组、日期、数字、布尔值、对象。
  • @thefrontender:你的意思是什么? (作为对此答案的评论)
  • @FelixKling 这是我评论时的最佳答案。 Questioner显然对JS中的对象和函数之间的关系感到困惑。您认为此评论属于其他地方还是没有帮助?
  • @thefrontender:我以为你在以某种方式批评这个答案,但不明白为什么。现在我明白这只是附加信息。 可能作为对该问题的评论更好,但这没什么大不了的,我只是感到困惑。
  • 好的,我明白“字符串是一个函数;它返回一个字符串”。那么有可能用纯javascript来做吗?如果我们编写一个 Javascript 对象(即函数)并在其构造函数中创建一个自身的新实例以返回它,它会不会导致无限递归? (这只是出于对 Javascript 工作的好奇,不一定要解决特定问题)
【解决方案2】:

在第二个 sn-p 结束时,尝试console.log(val)。你会注意到你泄露了一个全局变量:

var arr = [1,2,3];
arr.map(MyString);
console.log(val); // "3"

当使用arr.map(MyString) 时,您将该构造函数作为函数调用,而没有new 来创建实例。而且,由于 MyString 没有 return 任何东西,您会在结果中得到 undefined。但是,您仍然设置了this.val,而this 不是实例,而是全局对象

String 不返回 undefined,因为它在 called without new 时有一个 return

当 String 作为函数而不是构造函数调用时,它会执行类型转换。

返回由ToString(value) 计算的字符串值(不是字符串对象)。如果未提供值,则返回空字符串""

您可以使用 MyString 来模仿这一点,首先检查 this 是否是一个实例,当 this 还不是一个实例时返回一个新实例:

function MyString(x) {
    if (this instanceof MyString) {
        this.val = x;
    } else {
        return new MyString(x);
    }
}

var arr = [1, 2, 3];
arr.map(MyString); // [ {val: "1"}, {val: "2"}, {val: "3"} ]

【讨论】:

  • 对泄露的“val”有很好的观察。我花了一段时间才明白。但答案并没有解决我的问题。请参阅我添加的更新。我不是在寻找实用的解决方案,只是想更好地理解 Javascript。
  • @Jayesh 关于your comment,您可以使用if (this instanceof ...) 避免无限递归。有了它,您可以修改this(当它是一个实例时)或return new MyString(x)(当它不是实例时)。如果需要,它应该只递归一次。我已经用一个例子更新了我的答案。
【解决方案3】:

那是因为String 一个函数。它返回一个根据传递给它的内容构造的字符串。例如,如果您调用String(100),它将返回"100"

【讨论】:

    猜你喜欢
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 2017-09-01
    • 2015-09-04
    • 2016-09-28
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    相关资源
    最近更新 更多