3

I have this situation:

const args = ['b','c','d'];
var foo = 'a';
args.unshift(foo);
fn.apply(ctx, args); // args => ['a','b','c','d'] ✅

I could use concat, but that would put foo at the end of the list:

const args = ['b','c','d'];
var foo = 'a';
fn.apply(ctx, args.concat(foo)); // args => ['b','c','d','a'] ❌

I am looking for "precat", so that I can create a new array with the new element at the front, what's the best way to do this with JS? I am open to anything that saves me a line of code :)

guest271314
  • 1
  • 15
  • 104
  • 177
Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • 1
    Is the answer to your question not included at question itself at `args.unshift(foo);`? – guest271314 Jul 17 '17 at 03:12
  • 3
    `fn.apply(ctx, [foo].concat(args))` or `fn.call(ctx, foo, ...args)` – Patrick Roberts Jul 17 '17 at 03:12
  • @PatrickRoberts sure, those are good, please add an answer – Alexander Mills Jul 17 '17 at 03:14
  • Perhaps you should [edit] the question to make it clearer that you want a function that returns the new array (hence the reason that `.unshift()` doesn't do the job). – nnnnnn Jul 17 '17 at 03:15
  • Ideally there would be args.precat(foo), that would be ideal..obviously "precat" is kind of a joke in terms of a name for a method. – Alexander Mills Jul 17 '17 at 03:15
  • @nnnnnn I think it's pretty clear right? Look at the last sentence of the question. – Alexander Mills Jul 17 '17 at 03:16
  • 1
    Well the first comment suggested `.unshift()`, so... – nnnnnn Jul 17 '17 at 03:18
  • I agree, there are two people that don't get what I am asking so I agree that maybe the question could be improved but I am not sure how. – Alexander Mills Jul 17 '17 at 03:19
  • Using the spread operator: `let args = ['b','c','d']; const foo = 'a'; args = [foo, ...args];` – Antonio Val Jul 17 '17 at 03:22
  • 1
    @AntonioVal spread is not an operator [What is SpreadElement in ECMAScript documentation? Is it the same as Spread operator at MDN?](https://stackoverflow.com/questions/37151966/what-is-spreadelement-in-ecmascript-documentation-is-it-the-same-as-spread-oper), [Is …foo an operator or syntax?](https://stackoverflow.com/questions/44934828/is-foo-an-operator-or-syntax) – guest271314 Jul 17 '17 at 03:24
  • "`.unshift()` prepends an element to an array, but it modifies the array and returns the length; I would like a method like `.concat()` that creates a new array and returns that array." Or something. – nnnnnn Jul 17 '17 at 03:26
  • @guest271314 that wasn't the point of my answer. But thanks, that was educational. – Antonio Val Jul 17 '17 at 03:54
  • This is a beautiful question...who is the presumably dashing OP? – Alexander Mills Jul 17 '17 at 04:53

2 Answers2

3

Two one-liners come to mind...

fn.apply(ctx, [foo].concat(args))

fn.call(ctx, foo, ...args)

The latter uses the ES2015 spread syntax.

Update

No, there is no Array#precat(), and for good reason as this is demonstrated to be quite trivial.

TC39/proposal-array-precat (I'm kidding! (maybe... (It was meant as a joke)))

Object.defineProperty(Array.prototype, 'precat', {
  configurable: true,
  writable: true,
  value: function precat() {
    return Array.prototype.concat.call([], ...arguments, this)
  }
})

console.log(['e', 'f', 'g'].precat('a', ['b', 'c'], 'd'))
starwed
  • 2,536
  • 2
  • 25
  • 39
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • Right, but I am specifically wondering if the precat functionality exists, sometimes these things do exist, just hard to search for them. – Alexander Mills Jul 17 '17 at 03:16
  • Ha dude, concat is also trivial given what you wrote, so then why would concat exist? sorry that doesn't make sense :) precat should exist, it just doesn't. – Alexander Mills Jul 17 '17 at 03:18
  • @AlexanderMills _" Right, but I am specifically wondering if the precat functionality exists"_ Yes, `.unshift()`, as demonstrated at OP – guest271314 Jul 17 '17 at 03:19
  • @AlexanderMills Asking "why" certain functions exist and others don't is quite pointless. It's the specification, that's the most direct answer. I've given you a working solution, and you are literally creating an issue out of nothing. – Patrick Roberts Jul 17 '17 at 03:20
  • 1
    *"and for good reason as this is demonstrated to be quite trivial"* - If that's the threshold for including stuff in the language I think a few other methods could've been omitted. – nnnnnn Jul 17 '17 at 03:30
  • 1
    @AlexanderMills there's your prollyfill, if you really want it. I'm sure you knew how to do that though. – Patrick Roberts Jul 17 '17 at 03:51
  • Patrick Roberts I was just pointing out that it would be completely illogical to claim that it makes more sense for concat to exist than precat. You suggested that it did make more sense, and that's illogical to me. That's all. – Alexander Mills Jul 17 '17 at 04:57
  • `precat()` is a trivial implementation if _using_ `concat()`. `concat()` existed before the `Symbol.iterator` construct was introduced to the language, but its implementation is quite less trivial since it returns a new array and allows passing both arrays and non-iterable objects in the parameter list. – Patrick Roberts Oct 24 '18 at 21:27
  • `precat` would be a nice thing to have, especially since I want to be able to chain it with map, concat, and other Array methods which return a new Array. While trivial to implement, I'm not sure I really want to modify `Array.prototype` in my app or library. I'd be really happy if I could use something that already exists in the language to get the chaining behavior that `precat` would have. – Mnebuerquo Jul 13 '22 at 17:58
2

You can create a function which returns a new Array() with first variable passed set at index 0 of resulting array, use spread element to concatenate array passed at second parameter to single array, or if no parameter is passed at second parameter, return an Array() having element passed at first parameter

const prepend = (element, array = []) => 
                  !element ? [] : Array.of(element, ...array);

prepend("a", ["b", "c", "d"]) // `["a", "b", "c", "d"]`

prepend("a") // `["a"]`

prepend() // `[]`
guest271314
  • 1
  • 15
  • 104
  • 177