0

As per MDN

The slice() method returns a shallow copy of a portion of an array

That means you could effectively just return the pointer to the starting index in O(1) time complexity. But in many discussions, I see O(n) specified (linked below).

Links:

Was taking a look into v8 implementation but didn't get it.
https://chromium.googlesource.com/v8/v8/+/4.3.49/src/string.js?autodive=0%2F%2F

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Well, that's a 10-year-old version of v8 for one, and if you're looking for Array::slice, I doubt string.js is the place to look. – AKX Jun 08 '22 at 05:26
  • Besides - why don't you measure it? Run a benchmark that takes various-length slices from an array (and do something with those slices too); if they all finish equally quickly, it's probably O(1)... – AKX Jun 08 '22 at 05:27
  • @AKX Shouldn't string and array methods act similarly in terms of time complexity? – abhinav4279 Jun 08 '22 at 05:32
  • What makes you think that? There are many ways to implement arrays and many ways to implement strings. – AKX Jun 08 '22 at 05:33

2 Answers2

5

(V8 developer here.)

Array.prototype.slice is O(n), where n is the number of elements in the slice.
String.prototype.slice is O(1), thanks to our implementation of SlicedStrings, which are just storing pointer, offset, length to the original string and avoid copying the characters (except when they're tiny, so that copying a handful of characters is actually cheaper and smaller than storing a reference; that's still O(1)).

The key difference is that strings are immutable, and arrays are not. When you do str1 = "Hello World"; str2 = str1.slice(2, 5);, since there is no way to modify str1's contents afterwards, str2 doesn't need to ensure that it's unaffected by any such modification.
When you do a = [1, 2, 3, 4]; b = a.slice(1, 3); a[1] = "changed"; console.log(b[0]);, then you expect to see 2, not "changed". That's why b has to be an actual copy. (In theory, a copy-on-write approach would be possible, but V8 doesn't do that for array slices.)

"Shallow copy" means that nested objects will not be copied. Example:

let nested = {property: "value"};
var a = [nested];
var b = a.slice(0, 1);
a[0].property = "new value";
console.log(a === b);          // false, `b` is a copy
console.log(a[0] === b[0]);    // true, `nested` was not copied
console.log(b[0] === nested);  // true
console.log(b[0].property);    // "new value"
jmrk
  • 34,271
  • 7
  • 59
  • 74
0

Based on my read (which is to say, I could be wrong, since V8 is a complicated beast) of this array-slice.tq source code, the answer is: "it depends".

If possible (and the heuristics as to when that might happen I didn't really get to), V8 optimizes things to essentially O(1) by just returning a copy-on-write view to the original array via ExtractFastJSArray.

When that fails, V8 allocates a new array and copies object (pointers) over, which is of course O(N).

The tq source code includes lots of "gotcha" cases, since JavaScript does allow you to call Array.prototype.slice() on things that aren't really arrays.

AKX
  • 152,115
  • 15
  • 115
  • 172