最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Passing a constructor to Array.map? - Stack Overflow

programmeradmin1浏览0评论

How can i do something like this:

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

This code throws an Error on Google V8:

SyntaxError: Unexpected number

I'am also tried:

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

with the same result.

How can i do something like this:

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

This code throws an Error on Google V8:

SyntaxError: Unexpected number

I'am also tried:

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

with the same result.

Share Improve this question edited Dec 28, 2011 at 22:07 Tom van der Woerdt 30k7 gold badges74 silver badges105 bronze badges asked Jun 28, 2011 at 7:24 setset 3112 silver badges7 bronze badges 3
  • That code should not result in a SyntaxError. (Even though the operation is questionable otherwise: if new is not used during the invocation then the constructor function is ... just a normal function.) Is that all the code? Can you create a minimal jsfiddle test-case? Does it have a SyntaxError in FF/IE? – user166390 Commented Jun 28, 2011 at 7:58
  • There is a mistake in my code. The Date.constructor is the Function object constructor. The Date object constructor is Date.prototype.constructor or just Date. – set Commented Jun 28, 2011 at 11:52
  • Found an answer. I will post it in a few hours. – set Commented Jun 28, 2011 at 12:07
Add a comment  | 

4 Answers 4

Reset to default 8

I think what the OP was looking for is strictly analogous to this:

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

I assume the reason is that this is really elegant, both in simple type-casting operations like above, and in more interesting tasks like converting one representation of something into a different representation, like so:

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

The problem with this appears to be that the new object, when created by passing the constructor to Array.map, is an extended version of the window; that is, this within the constructor refers to the global scope, which sucks because (1) it wasn't your goal to hang props on window, and (2) the objects you create this way are not unique instances.

For what it's worth, the original type-casting example isn't all it's cracked-up to be, either, because:

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

The only solution I've come up with so far requires writing the constructor differently -- which you obviously can't do for native types like Date:

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

var humans = animals.map(Human);

By defining the return value as a new object, we sever the connection between the global scope and this; at least, that's what I assume is going on here. (You could also return a JSON literal instead of invoking Object.)

If I want these objects to have an interesting prototype, I have to define it separately and then attach it explicitly:

// 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);

In this case, it's not just as good to return JSON, because there don't appear to be any effective ways to set the prototype of an object-literal; and even if you could, you never want this to be true:

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

I think the best way to ensure the new object has the desired prototype is to pass the would-be prototype as the argument to new Object().

Is this pattern ideal? I don't know. It seems a little weird, since there are now two symbols associated with creating humans: Human the constructor function, and HumanProto the explicit prototype. More importantly, this seems like a real barrier if you've already got an ecosystem of fun custom classes that weren't written to be compatible with this pattern.

There is probably a better way out there. Maybe someone will post it.

Is this what you're trying to do?

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

The map method just iterates an array using the callback function provided (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map). So:

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

What are you trying to get from this:

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

Update from comment:

The problem here is to create an array of Date objects with time values from array a by passing the Date object constructor to a map function. Anyway there is a mistake in the code(see comment to pst) – set

I see, so something like:

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

The Date is a function, so the Date.constructor is a constructor of a function. Proper call of the Date object constructor looks like this:

Date.prototype.constructor();

Or just:

Date();

The problem here is to create an array of Date objects with time values from array a, but it is impossible to call the Date object constructor and pass an arguments to it without a new operator (ECMA-262 15.9.2).

But it is possible for any object constructors that can be called as a functions with the same result as if i use the new operator (for instance the Error object constructor (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' } ]
发布评论

评论列表(0)

  1. 暂无评论