2
const x = [new Date(), 1663761716, (new Date()).toJSON()];
const y = x.map((v) => new Date(v));
console.log(y);

The code above transforms an array of Date, number, string into an array of 3 Dates.

My question is the second line. Of course it is already short enough, but it feels stupid to call a function in a lambda with the same parameter. There should be something like:

const y = x.map(Date.constructor);

But this doesn't work. Is there any way to pass a constructor as a parameter?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Jeffrey Chen
  • 1,777
  • 1
  • 18
  • 29
  • There is no "functional" wrapper for the `new` keyword – Bergi Sep 21 '22 at 12:24
  • You can't, because you need the `new`, otherwise `Date` returns a string. Even if you could, though, you'd have a new problem: you can't use `Date` / `new Date` **directly** as a `map` callback because (as the [linked answers](https://stackoverflow.com/questions/262427/) explain) `map` calls its target function with three arguments, and `Date` handles things differently when it gets just one argument vs. more than one. What you have is best, or alternatively write a named wrapper function you can reuse. – T.J. Crowder Sep 21 '22 at 12:24
  • @tjcrowder I don't think that's a good duplicate target – Bergi Sep 21 '22 at 12:24
  • @Bergi - There are two separate issues, so I used one of them. I suspect there'a dupetarget for the other as well, if you'd like to find it. – T.J. Crowder Sep 21 '22 at 12:25
  • @T.J.Crowder `Reflect.construct` takes an array of arguments, doesn't it? – Bergi Sep 21 '22 at 12:26
  • @T.J.Crowder Ah I see what you mean, `x.map(Date)` would get `Date` called with 3 arguments, but I don't think that's the OPs problem really – Bergi Sep 21 '22 at 12:26
  • @Bergi - Bugger, you're right (about `construct`). – T.J. Crowder Sep 21 '22 at 12:27
  • @Bergi - I'm not finding a duplicate target for the `new` aspect of this, are you? If not, no harm in reopening it. – T.J. Crowder Sep 21 '22 at 12:29
  • @T.J.Crowder Searching for "binding new operator [js]", I found only [this](https://stackoverflow.com/questions/44146598/binding-the-new-constructor-to-a-function-in-javascript) which is an exact duplicate but has no proper answer, and [this related question](https://stackoverflow.com/q/18462914/1048572) that doesn't give the expected answer either – Bergi Sep 21 '22 at 12:33
  • @Bergi - Looking more closely at that other question, I think it's [too messy](https://stackoverflow.com/questions/44146598/binding-the-new-constructor-to-a-function-in-javascript) to make a good dupetarget for this one. – T.J. Crowder Sep 21 '22 at 15:10

1 Answers1

1

Unfortunately, there's no shortcut for it. What you have is what you should do (either directly inline like that, or a reusable named function that does it). There are two reasons for that:

  1. Because of the need for new. There's no way to say to map "here's Date, but call it using new instead of just calling it normally" (other than what you're doing, using a wrapper function). (There was once a proposal for a way to do it, but it never progressed.) And you do need to call Date using new for your use case; calling Date without new returns a string representation of the date, not a Date object.

  2. Because map passes three arguments to the callback function, and Date treats being called with three arguments differently from how it treats being called with one argument. You want the one argument version in your case. See the answers to the question here for details (that question forces on parseInt, but it's the same problem — the function doing different things depending on how many arguments are provided).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875