4

I'm confused with the output.

var arrLike = {0:'Martin', 1:78, 2:67, 3:['L', 'M', 'P'], length: 4};

If I use slice() on arrLike:

var newArr = Array.prototype.slice.call(arrLike, 0);

Output:

console.log(newArr);
["Martin", 78, 67, Array[3]]

How does this happen? I can't wrap up my head around with the output.

1
  • What would you expect the output to be? That looks like exactly what slice(0) does. Commented Jan 14, 2016 at 18:31

2 Answers 2

7

Preface: Note that the Array[3] in your console output is just how the console is showing it to you. Your newArr is really:

["Martin", 78, 67, ['L', 'M', 'P']]

It happens because that's how slice is defined. Loosely speaking it:

  1. Creates a new, empty array
  2. Reads the length property of what you give it
  3. Loops through from the starting index (default 0) to the ending index (default length - 1); call the loop variable k
    1. Puts any property found in the object when asking it for property k into the array at index k - start.
  4. Sets the length of the returned array to k - start.
  5. Returns the array

Or (again very loosely):

function slice(start, end) {
    var n, k, result;
    start = arguments.length < 1 ? 0 : +start;
    end = arguments.length < 2 ? +this.length : +end;
    result = [];
    for (var k = start, n = 0; k < end; ++k, ++n) {
        if (n in this) {
            result[n] = this[k];
        }
    }
    result.length = n;
    return result;
}

All the gory details.

Since your arrLike object has a length property and has properties with the names 0, 1, 2, and 3, you get the result you've shown.

Sign up to request clarification or add additional context in comments.

1 Comment

Very intuitive. Thanks!
1

Check out the spec for slice(). The slice() function will default the end parameter, which you did not specify, to this.length, and...

  1. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).

Therefore, you're only pushing the first 4 non-element properties of the arrLike object into the new array.

Try using...

var arrLike = {0:'Martin', 1:78, 2:67, 3:['L', 'M', 'P'], length: 6, 4: 'test'};

3 Comments

"...and will use that value if it's typeof is === 'number'" No, it will use it if it's a number or it can be converted to a number (specifically, a length value).
"Therefore, you're only pushing the first 4 elements..." As opposed to what? There are only four things that can be called "elements" in it. The fifth thing (length) isn't an "element," it's a non-element property ("element" being the term we [and the spec] use for properties that have a name that fits the definition of an "array index").
@T.J.Crowder Thank you, +2 and +1 for your answer. I have updated my answer to reflect your comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.