npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@benwiley4000/array-replace

v0.1.0

Published

A minimal ponyfill/polyfill implementing proposed `Array.prototype.replace` for ECMAScript (JavaScript)

Downloads

4

Readme

array-replace

A minimal ponyfill/polyfill implementing proposed Array.prototype.replace for ECMAScript (JavaScript)

arrayReplace(array, index, value)

const array1 = [1,2,3];
const array2 = arrayReplace(array1, 1, 4); // [1,4,3]

or ...

arrayReplace(array, replacements)

const array3 = [1,2,3,4,5];
const array4 = arrayReplace(array3, { 1: 7, 3: 48 }); // [1,7,3,48,5]

... or you can even polyfill it!

Array.prototype.replace(index, value) / Array.prototype.replace(replacements)

arrayReplace.polyfill();
const array2 = array1.replace(1, 4); // [1,4,3]
const array4 = array3.replace({ 1: 7, 3: 48 }); // [1,7,3,48,5]

including

In Node/Webpack/Browserify/Rollup/etc:

npm install @benwiley4000/array-replace
const arrayReplace = require('array-replace');

// if you want to polyfill...
arrayReplace.polyfill();
// ...etc

In a browser script tag:

<script src="https://unpkg.com/@benwiley4000/array-replace"></script>
<script>
  // if you want to polyfill...
  arrayReplace.polyfill();
  // ... etc
</script>

why?

With all the nice additions to the ECMAScript standard library and syntax lately enabling expressive programming without mutation, one common operation stands out as cumbersome: cloning and replacing an item from an array.

// step 1
const array1 = [1,2,3];

// step 2
const array2 = [...array1];

// step 3
array1[1] = 4; // [1,4,3]

These days with Object rest spread syntax, such an operation with normal objects is easy to do in one line.

// step 1
const object1 = { foo: 'hey', bar: 'ho' };
// step 2
const object2 = { ...object1, foo: 'hello' }; // { foo: 'hello', bar: 'ho' }

some good reasons

Ok, so you had to waste one more line... so what? Here are some good reasons:

  1. Sometimes we want to express update logic inline inside of an object literal.

    Here's an example of how array replacement can complicate what would otherwise be a single-statement function:

    function stateUpdater(oldState, newStuff) {
      const newNumbers = [...oldState.numbers];
      newNumbers[newStuff.numberReplacement.index] =
        newNumbers[newStuff.numberReplacement.value];
      return {
        ...oldState,
        newCount: oldState.count + newStuff.count,
        newNumbers
      };
    }

    We can use an immediately-invoked function expression (IIFE) to put that logic inline:

    function stateUpdater(oldState, newStuff) {
      return {
        ...oldState,
        newCount: oldState.count + newStuff.count,
        newNumbers: (() => {
          const newNumbers = [...oldState.numbers];
          newNumbers[newStuff.numberReplacement.index] =
            newNumbers[newStuff.numberReplacement.value];
          return newNumbers;
        })()
      };
    }

    However this is still verbose and there is a cost to allocating and executing a function inline. Now check out the same thing with Array.prototype.replace:

    function stateUpdater(oldState, newStuff) {
      return {
        ...oldState,
        newCount: oldState.count + newStuff.count,
        newNumbers: oldState.numbers.replace(
          newStuff.numberReplacement.index,
          newStuff.numberReplacement.value
        )
      };
    }
  2. Because it is generally less verbose, it can be tempting to use Array.prototype.splice, which mutates the original array. Inclusion of Array.prototype.replace discourages the practice of mutation for the sake of convenience.

    E.g. this, using splice, which mutates the input parameter:

    function replaceFifthElement(array, elem) {
      array.splice(4, 1, elem);
      return array;
    }

    is simpler to write than this, which does not mutate the input parameter:

    function replaceFifthElement(array, elem) {
      const newArray = [...array];
      newArray[4] = elem;
      return newArray;
    }

    ... but this, which also does not mutate the input parameter, is simpler than the first example.

    function replaceFifthElement(array, elem) {
      return array.replace(4, elem);
    }
  3. Each of the last two example functions can be written as arrow functions without a multi-statement body.

    const stateUpdater = (oldState, newStuff) => ({
      ...oldState,
      newCount: oldState.count + newStuff.count,
      newNumbers: oldState.numbers.replace(
        newStuff.numberReplacement.index,
        newStuff.numberReplacement.value
      )
    });
    
    const replaceFifthElement = (array, elem) => array.replace(4, elem);

alternative considerations

  • If runtime parameter typechecking is determined to be too expensive, we could have two methods: Array.prototype.replace and Array.prototype.replaceAll (for the object variant)
  • The object variant is included because it is slightly more performant than chaining .replace(index, value) many times in a row, but it's not necessarily clear that performance advantage would exist for a native implementation.
  • Consideration was given to a syntax extension instead of a standard library addition, similar to what is allowed by object rest spreading:
    const array = [
      ...[1,2,3],
      1: 4
    ];
    However, this syntax would probably be confusing since it would allow an array literal to declare members in duplicate fashion or out-of-order, which is currently possible for plain objects but not arrays.

contributing

Please feel free to open an issue to discuss anything!