Code Monkey home page Code Monkey logo

proposal-change-array-by-copy's Introduction

Note This proposal is 'finished' and has been merged into the ECMAScript spec. PR

Change Array by copy

Provides additional methods on Array.prototype and TypedArray.prototype to enable changes on the array by returning a new copy of it with the change.

Status

This proposal is currently at Stage 4.

Champions

  • Robin Ricard (Bloomberg)
  • Ashley Claymore (Bloomberg)

Reviewers

Overview

This proposal introduces the following function properties to Array.prototype:

  • Array.prototype.toReversed() -> Array
  • Array.prototype.toSorted(compareFn) -> Array
  • Array.prototype.toSpliced(start, deleteCount, ...items) -> Array
  • Array.prototype.with(index, value) -> Array

All of those methods keep the target Array untouched and returns a copy of it with the change performed instead.

toReversed, toSorted, and with will also be added to TypedArrays:

  • TypedArray.prototype.toReversed() -> TypedArray
  • TypedArray.prototype.toSorted(compareFn) -> TypedArray
  • TypedArray.prototype.with(index, value) -> TypedArray

These methods will then be available on subclasses of TypedArray. i.e. the following:

  • Int8Array
  • Uint8Array
  • Uint8ClampedArray
  • Int16Array
  • Uint16Array
  • Int32Array
  • Uint32Array
  • Float32Array
  • Float64Array
  • BigInt64Array
  • BigUint64Array

Example

const sequence = [1, 2, 3];
sequence.toReversed(); // => [3, 2, 1]
sequence; // => [1, 2, 3]

const outOfOrder = new Uint8Array([3, 1, 2]);
outOfOrder.toSorted(); // => Uint8Array [1, 2, 3]
outOfOrder; // => Uint8Array [3, 1, 2]

const correctionNeeded = [1, 1, 3];
correctionNeeded.with(1, 2); // => [1, 2, 3]
correctionNeeded; // => [1, 1, 3]

Motivation

The Tuple.prototype introduces these functions as a way to deal with the immutable aspect of the Tuples in Record & Tuple. While Arrays are not immutable by nature, this style of programming can be beneficial to users dealing with frozen arrays for instance.

This proposal notably makes it easier to write code able to deal with Arrays and Tuples interchangeably.

Relationship with Record & Tuple

While this proposal is derived from Record & Tuple, it should progress independently.

If web compatibility prescribes it, property names defined in this proposal are going to be changed. Those changes should be reflected on Tuple.prototype.

Implementations

proposal-change-array-by-copy's People

Contributors

acutmore avatar codehag avatar linusg avatar ljharb avatar mathiasbynens avatar netizen-ais avatar nicolo-ribaudo avatar rricard avatar slorber avatar syg avatar zloirock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

proposal-change-array-by-copy's Issues

SortCompare isn't usable by anything but `Array.prototype.sort`

It seems like SortCompare, which withSorted/toSorted uses, only has access to the "sort" method's comparefn.

In other words, I think that SortCompare needs to be refactored to somehow take comparefn as an argument rather than magically pulling it from the scope, otherwise both sort and toSorted won't be able to use it.

missing “filled"

I think these might be the only mutator methods not listed in the readme.

Spec needs `%` for intrinsics

3. Perform ? Call(Array.prototype.sort, A, «compareFn»)., for example, needs to be 3. Perform ? Call(%Array.prototype.sort%, A, «compareFn»).

Research web compatibility

Ensuring that no clashes exists between the web reality and this proposal is an essential precondition to Stage 3.

This will require research work with implementers.

`@@unscopables`

Those methods should be added to Array.prototype[@@unscopables].

New naming scheme: with<PastTense> and withAt

After the last Record & Tuple meeting, we would like to propose the following naming scheme for those methods. This new naming would be ported to Tuples as well:

  • .filled -> .withFilled
  • .copiedWithin -> .withCopiedWithin
  • .popped -> .withPopped
  • .pushed -> .withPushed
  • .reversed -> .withReversed
  • .shifted -> .withShifted
  • .sorted -> .withSorted
  • .spliced -> .withSpliced
  • .unshifted -> .withUnshifted
  • .with -> .withAt

This new naming scheme would still be subject to future changes but is closer to what we would end up implementing.

The rationale behind this change is the following:

  • Makes theose methods more easy to distinguish in a conversation from their mutator counterparts
  • Naming scheme now also encompasses the `.withAt' operation
  • We estimate a reduced risk of webcompatibility issues with this new naming

This issue can be used to discuss immediate technical objections to this naming scheme but will mainly serve to track changes to the spec text and the polyfill. If you want to discuss naming alternatives, please refer to #10.

Alternative approaches

Description

I'm sorry if understood the proposal wrong or didn't research it well enough but why it's better to have toReversed(), toSorted() along with reverse(), sort()? (I can agree with toSpliced() and with(...))

I can't really see the problem to just use spread syntax or "standard" method, I'll demonstrate it on your examples.

reverse()

Proposal approach

const sequence = [1, 2, 3];
sequence.toReversed(); // => [3, 2, 1]
sequence; // => [1, 2, 3]

Spread syntax approach

const sequence = [1, 2, 3];
[...sequence].reverse(); // => [3, 2, 1]
sequence; // => [1, 2, 3]

sort()

Proposal approach

const outOfOrder = new Uint8Array([3, 1, 2]);
outOfOrder.toSorted(); // => Uint8Array [1, 2, 3]
outOfOrder; // => Uint8Array [3, 1, 2]

"Standard" approach

const outOfOrder = new Uint8Array([3, 1, 2]);
new Uint8Array(outOfOrder).sort(); // => Uint8Array [1, 2, 3]
outOfOrder; // => Uint8Array [3, 1, 2]

Conclusion

As you can see it's not a big problem to solve this with already existed methods it's niether making code a lot longer nor more complicated.
If you can give more examples on what your proposal solves with real-world examples, otherwise it's just polution of the Array and TypeArray, a newbie would barely see the diffrence and why there splice() and toSpliced() at the same time.

Again, maybe I don't get it and not taking something to an account. However your examples showing only with(...) usage as "reasonable" (as for me).

Items for TC39 2022 July Plenary

We have some updates about %TypedArray%.prototpe.toSpliced to present at the next plenary. This ticket serves as an 'entry' point to them.

  • Question was asked if we should keep it. We plan to keep it.
  • Updates to process arguments earlier

Should the `CreateDataPropertyOrThrow` invocation in `Array.prototype.sort` be changed to `Set`?

Hello,

We've implemented this proposal over in SerenityOS's LibJS and noticed a potential issue in Array.prototype.sort:

In ECMA-262, step 7 of SortIndexedProperties loops from the index j to itemCount to invoke Set on the provided obj. In this proposal, this step (and step 8) were pulled out of SortIndexedProperties so that callers handle the resulting item list differently.

Array.prototype.sort now invokes CreateDataPropertyOrThrow instead of Set. However, a handful of existing test262 tests fail with this change:

Diff Tests:
    test/built-ins/Array/prototype/sort/precise-getter-appends-elements.js    ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-getter-decreases-length.js    ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-getter-deletes-predecessor.js ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-getter-deletes-successor.js   ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-getter-increases-length.js    ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-getter-pops-elements.js       ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-getter-sets-predecessor.js    ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-getter-sets-successor.js      ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-prototype-accessors.js        ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-setter-appends-elements.js    ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-setter-decreases-length.js    ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-setter-deletes-predecessor.js ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-setter-deletes-successor.js   ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-setter-increases-length.js    ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-setter-pops-elements.js       ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-setter-sets-predecessor.js    ✅ -> ❌
    test/built-ins/Array/prototype/sort/precise-setter-sets-successor.js      ✅ -> ❌

I believe these tests now throw an exception due to step 5a of ValidateAndApplyPropertyDescriptor when CreateDataPropertyOrThrow is invoked.

Should Array.prototype.sort be reverted to the old behavior of invoking Set instead? These tests all pass with that change.

`ArrayClone` question

%Array.prototype.slice% already is "ArrayClone" - if it's better as a separate abstract operation, should slice itself be updated to use it?

Bogus length validation in Array.prototype.toSpliced

Array.prototype.toSpliced does this:

12. If newLen > 2^53 - 1, throw a TypeError exception.
13. Let A be ? ArrayCreate(𝔽(newLen)).

But ArrayCreate does this:

1. If length > 2^32 - 1, throw a RangeError exception.

Couple of issues:

  • Why is the length validated to be in a range much larger than the immediate next step allows in the first place?
  • Why TypeError and not RangeError - this seems to be inherited from Array.prototype.splice, which uses ArraySpeciesCreate and only passes actualDeleteCount as the length in the next step however
  • Is it intentional that depending on how much too large (i.e. above 2^32 - 1) the value is you'll get a different error type?

Accept string index argument in `{Array, TypedArray}#withAt`

I agree with the introduction of integer value checking in {Array, TypedArray}#withAt, which was not considered in {Array, TypedArray}#at. However, the current specification always throws a RangeError in the case of a string.

It's complicated, but I think we can avoid this problem by changing the specification as follows:

let numericIndex;

if (typeof index === "string") {
  numericIndex = CanonicalNumericIndexString(index);
  if (numericIndex === undefined) {
    throw TypeError("Invalid index type");
  }

} else if (typeof index === "number") {
  numericIndex = index;

} else {
  throw TypeError("Invalid index type");
}

if (!IsIntegralNumber(numericIndex)) {
  throw RangeError("Invalid index");
}

// accept number -0
if (SameValue(numericIndex, -0)) {
  // IsValidIntegerIndex rejects -0, so overwrite it with 0
  numericIndex = 0;
}

without: remove elements from array?

Hi,

This proposal looks great and would be happy to see these methods added to JS

However, there is one method that I feel is always lacking in JS and is a very common usecase: remove item(s) from an array by value/identity. Just suggestion if this can be considered as part of this proposal?

In UI development we often need to "toggle" values in list, for example let's consider a tag selection UI:

function toggleTag(tagList,tag)  {
  return tagList.includes(tag) ? tagList.concat(tag) : tagList.filter(t => t !== tag)
}

Using _.without(tagList,tag) looks more expressive, particularly when you need to remove multiple values at once.

Also think this method would play well with records in a tuple as it would work with tags like#{name: "TagName", id: "tagId"}

This is just an idea, just close if this is not the good place to ask for this ;)

Types broken when array is marked as readonly

withAt types work OK as long as array is NOT marked as readonly

let a1 = [11, 22, 33]

a1.withAt(2, 222)

let a2 = [11, 22, 33] as readonly number[]

a2.withAt(2, 222)

// Property 'withAt' does not exist on type 'readonly number[]'.ts(2339)

Target %TypedArray% directly, not its subclasses

From the README:

For all the above methods, replace TypedArray with one of the following accordingly:

  • Int8Array
  • Uint8Array
  • Uint8ClampedArray
  • Int16Array
  • Uint16Array
  • Int32Array
  • Uint32Array
  • Float32Array
  • Float64Array
  • BigInt64Array
  • BigUint64Array

Does this indicate that the prototype methods would exist on each seperate class's prototype? It currently reads like this is the case.

Usually TypedArray methods are added directly to the %TypedArray%.prototype object. The recent stage three, indexed .at method even does the same.

If the methods will indeed exist on %TypedArray%, a bit of rewording might help resolve the ambiguity here.

Consider `.mutatedCopy(mutatorFunction)`

During our session today, I was struck by how painful all this bikeshedding on names is and how it'll end up having to be done for every method added in the future, too.

I felt inspired to come up with a way to have just one method and allow easy reuse of the existing, mutating methods instead of creating new ones.

Here's my proposal in the form of a polyfill for Array.

Array.prototype.mutatedCopy = function(mutatorFunction = copy => copy) {
  // Make a mutable copy.
  // For mutable things like Array and TypedArray, this copy will be the actual final value.
  // For Tuple we will create an Array here, so the mutatorFunction can change it.
  const copy = [...this];
  mutatorFunction(copy);
  // The Tuple version of this method will convert the copy to a Tuple here.
  return copy;
};

const ary123 = [1, 2, 3];

// Note that we don't care about what the return value of our arrow function is,
// so we don't have to deal with the fact that `.push()` returns a number, not the array.
const ary123abc = ary123.mutatedCopy(copy => copy.push('a', 'b', 'c'));

// You can do any mutation you want.
const ary234 = ary123.mutatedCopy(copy => { copy.shift(); copy.push(4); } );

I'm sure some folks won't like having to define the arrow function,
but to me it doesn't seem like a big cost for the flexibility it provides.

The primary downside I see here is that this approach always creates a complete copy of the original.
With the custom methods approach the VM could theoretically avoid copying all of a large array for a call like
array.spliced(0, 500).

Researching existing code corpora

An issue to collect discussions/results around researching existing code to extract data that may help with the design/scope of this proposal.

Array Method Usage

Using the GitHub dataset on BigQuery to scan for usage on existing array methods.

Number of repositories that include a particular method call

Query
SELECT
SUM(1) AS js_repos,
SUM(CAST(has_map AS INT64)) AS has_map,
SUM(CAST(has_filter  AS INT64)) AS has_filter,
SUM(CAST(has_reduce  AS INT64)) AS has_reduce,
SUM(CAST(has_copy_within  AS INT64)) AS has_copy_within,
SUM(CAST(has_fill  AS INT64)) AS has_fill,
SUM(CAST(has_pop  AS INT64)) AS has_pop,
SUM(CAST(has_push  AS INT64)) AS has_push,
SUM(CAST(has_reverse  AS INT64)) AS has_reverse,
SUM(CAST(has_shift  AS INT64)) AS has_shift,
SUM(CAST(has_sort  AS INT64)) AS has_sort,
SUM(CAST(has_slice  AS INT64)) AS has_slice,
SUM(CAST(has_slice_default AS INT64)) AS has_slice_default,
SUM(CAST(has_slice_pop  AS INT64)) AS has_slice_pop,
SUM(CAST(has_slice_shift  AS INT64)) AS has_slice_shift,
SUM(CAST(has_splice AS INT64)) AS has_splice,
SUM(CAST(has_unshift AS INT64)) AS has_unshift,
FROM (
SELECT
  repo_name,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.map\(")) AS has_map,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.filter\(")) AS has_filter,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.reduce\(")) AS has_reduce,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.copyWithin\(")) AS has_copy_within,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.fill\(")) AS has_fill,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.pop\( ?\)")) AS has_pop,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.push\(")) AS has_push,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.reverse\( ?\)")) AS has_reverse,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.shift\( ?\)")) AS has_shift,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.sort\(")) AS has_sort,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.slice\(")) AS has_slice,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.slice\(\)")) AS has_slice_default,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.slice\( ?0 ?, ?-1 ?\)")) AS has_slice_pop,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.slice\( ?1 ?\)")) AS has_slice_shift,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.splice\(")) AS has_splice,
  LOGICAL_OR(REGEXP_CONTAINS(content, r"\.unshift\(")) AS has_unshift,
FROM (
  SELECT
    repo_name,
    content
  FROM
    `bigquery-public-data.github_repos.files`
  INNER JOIN
    `bigquery-public-data.github_repos.contents`
  USING
    (id)
  WHERE
    ENDS_WITH(path, '.js')
    AND NOT REGEXP_CONTAINS(path, r"\d\.\d"))
GROUP BY
  repo_name )

To get a general sense of the relative usage of the methods that we are proposing to add non-mutating versions of (and other methods like .map as a benchmark).

  • Tries to exclude files that are copies of libraries by excluding file paths that seem to contain a version /\d.\d/
  • Does not exclude forks (tbc)
  • Includes false positives. .map could be Observable.prototype.map and .slice could be String.prototype.slice
  • Dataset is from 2016 (tbc)
Category Count %
All repos with .js 1,187,155 100
.push(... 813,437 69
.slice(... 625,390 53
.map(... 624,565 52
.filter(... 571,678 48
.sort(... 536,098 45
.splice(... 533,482 45
.shift() 500,447 42
.pop() 497,781 42
.unshift() 434,742 37
.reverse() 403,688 34
.reduce(... 248,995 21
.fill(... 141,936 12
.copyWithin(... 6,034 0.5

Slice usage

.withPopped() is ~equivalent to .slice(0, -1) and .withShifted() is ~equivalent to .slice(1). So we can also look for those particular patterns.

Category Count %
All repos with .js 1,187,155 100
.slice(... 625,390 53
.slice(1) 434,558 37
.slice(0, -1) 264,466 22

Extra param alternative?

What if instead of adding new methods, we just add a new parameter that takes a Boolean argument that specifies whether to copy or mutate? This could also be added to other methods like fill, filter, flat, map, and slice. This would simplify code like this:

arr = arr.slice(i0, i1)

Into this

arr.slice(i0, i1, true)

That way, every Array method will be capable of mutation and shallow copying, and devs could explicitly specify which behavior they want. Instead of a Bool arg, it could be strings (for readability) like 'mut' & 'copy'.

arr = arr.map(_ => _, null, 'copy')
//is equivalent to
arr.map(_ => _, null, 'mut')

The problem with this is that some methods are variadic, so they can't have an extra param, and would require a new fn. This is the case of concat, push, and some others

missing "copiedWithin" ?

See #4

copyWithin(target, start, end) could see a copiedWithin alternative, but the signature would have to be different to make sense...

Introduce array.prototype.clone

Instead of creating a new immutable versions of methods that already exist, could we not introduce a single .clone() method that returns a copy of the array that can be mutated safely.

This can be used in conjunction with all existing functions and instead on introducing a new function for each use case. As developer it would reduce cognitive overload, since you're likely to get confused by naming scheme with the ed suffix.

To change: Reduction of scope

This issue is a consolidation of #24 by @benlesh (thanks for opening the discussion on this!)


This thread intends to propose the following reduction of scope. This has been discussed in the last Record & Tuple meeting but has not been validated, pending the definition fo the exact scope and further discussion.

-   Array.prototype.filled(value, start, end) -> Array
-   Array.prototype.copiedWithin(copiedTarget, start, end) -> Array
-   Array.prototype.popped() -> Array
-   Array.prototype.pushed(values...) -> Array
+   Array.prototype.reversed() -> Array
-   Array.prototype.shifted() -> Array
+   Array.prototype.sorted(compareFn) -> Array
+   Array.prototype.spliced(start, deleteCount, ...items) -> Array
-   Array.prototype.unshifted(...values) -> Array
+   Array.prototype.with(index, value) -> Array

# Key:
-   to be removed
+   will be kept

updated to reflect our current intent to change (See #27 (comment) )

The rationale behind this proposed change is that those functions could be replaced with slice & concatenation techniques that would be as explicit. It would also prevent unwanted over-copying of arrays, notably by preventing chaining of those operations. Finally it reduces web-compatibility risk.

The main objection would be that those methods have been designed around Tuples in the first place and could be useful there. As we want to keep both proposals in sync we would have to remove them from Tuples as well.

Alternative to `toSpliced()`

Sorry it's too late to add this issue, I commented that on the yesterday meeting. Though I didn't want to block this proposal in the meeting, I think we still have chance to think about the alternative.

The problems of splice, toSpliced

There are many complaints about the old splice method in the community, the main issues of it are:

  • Bad name: splice is a very uncommon word, as word usage frequency from COCA (Corpus of Contemporary American English) , "splice" is at the position of 20171, and as this comment, even native speakers might not know the meaning of that word anymore.
  • Bad api: It's so hard to figure out what the code like a.splice(1, 2, 3, 4, 5) really do.
  • Combination of the bad name and api: the name of splice looks very like slice, so those who don't know the word well would guess it's a mutation version of slice, but it not follow slice api.

toSpliced() inherit all these warts, and might worse because it return semantics differ from splice, this means if you would see code like:

let originalSlice = a.slice(start, end)
let newArray = a.toSpliced(start, end - start, ...items)

Not easy to understand and maintain, and it's even have random bug when start or end are negative!

Alternative

Do not add toSpliced but add:

a.sliceReplace(start, end, items)
a.withSliceReplaced(start, end, items)

which follow the convention of slice, solve the problems.

Note, this could be a separate proposal, but if we had withSliceReplaced(start, end, items), it's no need to add a bad api like toSpliced anymore.

popped, shifted, unshifted, pushed are likely redundant

  • popped and shifted are basically variations on slice.
  • unshifted and pushed are variations on concat.

This is the guy who works on RxJS telling you not to add too many redundant methods. (serious :pot: :kettle: 🖤 energy) It will only serve to create confusion. In particular since they are so similarly named to existing APIs. I can already see the bugs slipping through code reviews.

Allow Array methods to operate on 'array like' values (e.g. strings)

Context:

Existing Array methods can also be called with an array-like receiver:

Array.prototype.map.call({ length: 1, 0: 41 }, v => v + 1); // [42]
Array.prototype.flat.call("test"); // ["t", "e", "s", "t"]

Issue:

Do we allow the new Array methods in this proposal to also work on 'array-like' values?

Array.prototype.pushed.call("te", "s", "t");  // ["t", "e", "s", "t"]

`toReversed()` is not reversible on sparse arrays

I can (with great regret) live with the fact that toSorted() eliminates empty slots (although I think symmetry with functionally similar APIs is much more charitable than symmetry by the time they were introduced—cf flatMap, findLast). However, the fact that toReversed() is not reversible bothers me.

[1, , 3].toReversed().toReversed(); // [1, undefined, 3]
[, , , ].toReversed(); // This is a symmetrical array; toReversed should be idempotent!

This makes its explanation unnecessarily harder, compared to just saying "every element is swapped", which automatically covers the empty slot case.

Why the naming

What is the reason by the name toSpliced() and not something like removeValues() or replaceValues()?
And why with() and not something like replaceValue()?

toSpliced differences from splice

I notice that Array splice has a step If len + insertCount - actualDeleteCount > 2 ** 53 - 1, throw a TypeError exception. - but toSpliced does not. Is that intentional?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.