test2 doesn't produce the result you expect because you're calling it on a non-array-like object: it's missing length. test1 and test3 produce the result you expect because you're calling it on array-like objects. Since test2 is missing length, when slice reads length, it gets undefined, which gets converted to NaN, so 0 gets used as the length of the source array. (If you're curious, in the spec it's slice -> LengthOfArrayLike(obj) -> ToLength(obj.length) -> ToInteger(undefined) -> ToNumber(undefined); ToNumber returns NaN, which ToInteger converts to 0.)
If we add length to test2, it also produces what you expect:
/*eslint-disable no-console */
var testFunc = function(){
console.log(arguments);
console.log("test3: ", Array.prototype.slice.apply(arguments));
};
testFunc(1,2);
console.log("test1: ", Array.prototype.slice.apply([1,2]));
console.log("test2: ", Array.prototype.slice.apply({0:1, 1:2, length:2}));
.as-console-wrapper {
max-height: 100% !important;
}
Side note: No need for computed property notation when building the array-like object for test2, numeric literals are valid property names in object literals (I've removed the computed notation in the snippet above).