(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"