将构造函数传递给Array.map?

时间:2011-06-28 07:24:23

标签: javascript arrays map constructor prototype-programming

我该怎么做:

var a = [1,2,3,4];
a.map(Date.constructor);

此代码在Google V8上引发错误:

SyntaxError: Unexpected number

我也尝试过:

a.map(Date.constructor, Date.prototype)

具有相同的结果。

4 个答案:

答案 0 :(得分:4)

我认为OP正在寻找的东西与此类似:

var nums = [1, 2, 3];
var strs = nums.map(String);
//=> ['1', '2', '3']; // array of strings

我认为原因在于,这非常优雅,无论是在上面的简单类型转换操作中,还是在更有趣的任务中,例如将某个表示形式转换为不同的表示形式,如下所示:

function MyCoolObject(oldObject) {
    // generates new object by consuming old one
    // maybe attach some cool class methods via prototype
    return this;
}

var newList = oldList.map(MyCoolObj);
//=> array of MyCoolObj based on oldObject

这个问题似乎是新对象在通过将构造函数传递给Array.map创建时,是window的扩展版本;也就是说,构造函数中的this指的是全局范围,这很糟糕,因为(1)你的目标不是挂在window上的道具,和(2)你创造的对象方式不是唯一的实例。

对于它的价值,原始的类型转换示例并非全部被破解,因为:

strs[0] instanceof String
//=> false // UGH!

到目前为止,我提出的唯一解决方案需要以不同的方式编写构造函数 - 您显然可以对Date等本机类型执行此操作:

function Human(animal) {
    var h = new Object();
    h.species = 'human';
    h.name = animal.name;
    return h;
}

var humans = animals.map(Human);

通过将返回值定义为新对象,我们切断了全局范围与this之间的连接;至少,我认为这是在这里发生的事情。 (您也可以返回JSON文字而不是调用Object。)

如果我希望这些对象有一个有趣的原型,我必须单独定义它,然后明确地附加它:

// this object will be used as the prototype for new Human instances
var HumanProto = {
    species: 'human',
    speak: function() { console.log('My name is ' + this.name); },
    canDrink: function() { return this.age >= 21; }
}

// then, in Human, make this change
var h = new Object(HumanProto);

在这种情况下,返回JSON并不是那么好,因为似乎没有任何有效的方法来设置对象文字的原型;即使你可以,你也绝不希望这个是真的:

myObject.hasOwnProperty('prototype');
//=> true // only if myObject = { prototype: HumanProto }

我认为确保新对象具有所需原型的最佳方法是将可能的原型作为参数传递给new Object()

这种模式是否理想?我不知道。这似乎有点奇怪,因为现在有两个与创建人类相关的符号:Human构造函数,HumanProto显式原型。更重要的是,如果您已经拥有一个有趣的自定义类生态系统,而这些自定义类没有被编写为与此模式兼容,那么这似乎是一个真正的障碍。

可能有更好的方法。也许有人会发布它。

答案 1 :(得分:3)

这是你想要做的吗?

var a = [1, 2, 3, 4];
a.map(function(obj) { return new Date(obj); });

答案 2 :(得分:0)

map方法使用提供的回调函数迭代数组(https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map)。所以:

var a = [1,2,3,4];
a.map(function(b) { return b+10; }); // [11, 12, 13, 14]

你想从中得到什么:

Date.constructor(1);
Date.constructor(2);
Date.constructor(3);

评论更新:

  

这里的问题是创建一个数组   具有时间值的Date对象   通过传递Date对象来数组a   构造函数到map函数。无论如何   代码中有错误(请参阅   评论pst) - 设置

我明白了,所以:

var a = [1,2,3,4];
a.map(Date.prototype.constructor);

答案 3 :(得分:-3)

Date是一个函数,因此Date.constructor是函数的构造函数。 正确调用Date对象构造函数如下所示:

Date.prototype.constructor();

或者只是:

Date();

这里的问题是创建一个Date对象数组,其中包含数组a的时间值, 但无法调用Date对象构造函数并在没有new运算符的情况下向其传递参数(ECMA-262 15.9.2)

但是可以将任何对象构造函数调用为具有相同结果的函数,就像我使用new运算符一样(例如,错误对象构造函数(ECMA-262 15.11.1))。

$ var a = ['foo','bar','baz'];
$ a.map(Error);
> [ { stack: [Getter/Setter], arguments: undefined, type: undefined, message: 'foo' },
    { stack: [Getter/Setter], arguments: undefined, type: undefined, message: 'bar' },
    { stack: [Getter/Setter], arguments: undefined, type: undefined, message: 'baz' } ]