Javascript Array.prototype.slice异常行为

Javascript Array.prototype.slice异常行为,javascript,Javascript,考虑这段代码,每行末尾都有控制台输出: function whatever() { console.log(arguments) // { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 } console.log(Array.prototype.slice.call(arguments)) // [ 1, 2, 3, 4, 5 ] console.log(Array.prototype.slice.call({ '0': 1, '1': 2, '2':

考虑这段代码,每行末尾都有控制台输出:

function whatever() {
  console.log(arguments) // { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
  console.log(Array.prototype.slice.call(arguments)) // [ 1, 2, 3, 4, 5 ]
  console.log(Array.prototype.slice.call({ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 })) // []
}

whatever(1,2,3,4,5)

为什么第三个
控制台.log
输出一个空数组?

因为要使
array.prototype.slice
工作,需要传递一个类似数组的对象。为了使对象适合该类别,它需要一个
length
属性,而您的对象没有该属性。试试这个:

var arr = { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 };
arr.length = 5;
var res = Array.prototype.slice.call(arr);
console.log(res);

尽我所知

参数是一个对象类型的变量,我们可以使用它来获取传递给方法的每个参数的条目

例如,如果我们使用这个

whatever(a,b,c)
参数将返回类似
0:a、1:b、2:c的内容

切片方法用于从起点到终点对数组进行切片,如

var myarray=["1","2","3","4"];
myarray.slice(2,3);
将返回索引2和3上存在的3和4

所以,如果你想在你的参数上使用slice,只需像
slice(startindex,endindex)那样定义它


仅一个edit slice.call用于将一个数组类型转换为另一个数组类型的数据结构,在您的例子中,由于它是javascript引擎的已知类型,所以在传递参数时,它将其视为数组类型并简单地进行转换,但对数组进行硬编码似乎不起作用(只是一个想法)。

如@basilikum所述,这是因为使用
.slice()
需要
.length
。要理解为什么需要它,请假设您在阅读MDN文档后正在编写自己版本的
Array.prototype.slice()


语法 参数
开始

从零开始提取的索引

作为负索引,
begin
表示从序列末尾的偏移量<代码>切片(-2)
提取序列中倒数第二个元素和最后一个元素

结束

结束提取的从零开始的索引<代码>切片
提取到但不包括
结束

slice(1,4)
通过第四个元素(索引为1、2和3的元素)提取第二个元素

作为负索引,
end
表示与序列末尾的偏移量<代码>切片(2,-1)通过序列中倒数第二个元素提取第三个元素

如果省略了
end
slice
提取到序列的末尾


要处理所有这些情况以及其他一些未列出的情况,您的代码必须符合以下要求(这可能有bug,但应该很接近):

Array.prototype.myslice=函数(开始,结束){
//使用数组长度,如果缺少,则使用0
var length=this.length | | 0;
//句柄缺少开始
如果(begin==未定义)begin=0;
//句柄负开始,从数组长度偏移
如果(开始<0)开始=长度+开始;
//但要确保它不会小于0
如果(开始<0)开始=0;
//句柄缺少端点或端点过长
如果(end==未定义| | end>长度)end=长度;
//处理负端(不必担心<0)
如果(末端<0)末端=长度+末端;
//现在复制元素并返回结果数组
var结果=[];
对于(变量i=开始;i<结束;++i)
结果.推(这个[i]);
返回结果;
};

这就是为什么
.slice()
需要
此.length
-如果没有它,您将无法编写函数。

如果您获得可枚举键length
arr.length=Object.keys(arr).length
@Givi,而不是以这种方式分配长度,可能会更好。但是为了更接近数组的实际行为,您必须将
length
属性设置为最高的数字键加1
arr.length=Object.keys(arr).filter(函数(项){return/^[0-9]+$/.test(项);}).sort(函数(a,b){return b-a})[0]+1。无论如何,这只是一个例子,说明它是有效的,只要您正确设置了
length
属性:)这是一个漂亮的解决方案,但排序在这种情况下是无用的,我想是这样;)和
排序(…)[0]+1
;与“4”+1相同,等于41。也许你应该在过滤后得到长度,
过滤器(…).length
,甚至像数组一样的对象在切片时也不会被排序,它会按它应该的顺序排序;)即使在object中还有其他属性,如
“someProperty”:“some value”
,在切片时也不会添加这些属性。@Givi您是对的,在添加1之前需要将键转换为数字。我错过了。但是我想你还是要对它进行排序,因为你不想要键的数目,而是想要最高的键。如果键为0,1,3,则希望长度为4,就像在实际数组中一样。是的,当您选择它时,将不会添加非数值特性。但是你在切片之前计算长度,因此你必须过滤掉它们。
Array.slice(begin[, end])
Array.prototype.myslice = function( begin, end ) {
    // Use array length or 0 if missing
    var length = this.length || 0;
    // Handle missing begin
    if( begin === undefined ) begin = 0;
    // Handle negative begin, offset from array length
    if( begin < 0 ) begin = length + begin;
    // But make sure that didn't put it less than 0
    if( begin < 0 ) begin = 0;
    // Handle missing end or end too long
    if( end === undefined  ||  end > length ) end = length;
    // Handle negative end (don't have to worry about < 0)
    if( end < 0 ) end = length + end;
    // Now copy the elements and return resulting array
    var result = [];
    for( var i = begin;  i < end;  ++i )
        result.push( this[i] );
    return result;
};