Nodejs中array.slice的类里为什么不能这么用

Nodejs中array.slice的类里为什么不能这么用

    var invokeCb = function(cb) {
console.log( arguments.slice(1));
console.log( Array.prototype.slice.call(arguments, 1));
}

invokeCb(‘aa’,‘bb’,‘cc’,‘dd’);

为什么 console.log( arguments.slice(1)); 这句是错误 而 console.log( Array.prototype.slice.call(arguments, 1)); 而这句是正常的

求解


4 回复

当然可以。让我们来详细分析一下这段代码,并解释为什么 console.log( arguments.slice(1)); 会出错,而 console.log( Array.prototype.slice.call(arguments, 1)); 却是正确的。

问题背景

在JavaScript中,函数内的 arguments 对象是一个类数组对象,它包含了传递给函数的所有参数。然而,arguments 对象并不是一个真正的数组,因此它没有数组原型上的方法(如 slice)。

示例代码分析

var invokeCb = function(cb) {
    console.log( arguments.slice(1));
    console.log( Array.prototype.slice.call(arguments, 1));
}

invokeCb('aa', 'bb', 'cc', 'dd');

第一行输出:console.log( arguments.slice(1));

在这行代码中,我们尝试直接调用 arguments.slice(1)。由于 arguments 对象不是一个真正的数组,它并没有 slice 方法。因此,这会导致一个错误,类似于:

TypeError: arguments.slice is not a function

第二行输出:console.log( Array.prototype.slice.call(arguments, 1));

在这行代码中,我们使用了 Array.prototype.slice.call(arguments, 1) 的方式来调用 slice 方法。这种方式利用了 call 方法将 slice 方法绑定到 arguments 对象上,并传递了需要切片的起始索引 1。这样,即使 arguments 不是一个真正的数组,我们也能通过借用数组的方法来操作它。

正确的输出

当你运行这段代码时,第二行输出将是:

[ 'bb', 'cc', 'dd' ]

这是因为 Array.prototype.slice.call(arguments, 1)arguments 对象当作数组来处理,从索引 1 开始获取所有元素。

总结

总结来说,arguments 对象虽然看起来像一个数组,但它实际上是一个类数组对象。为了正确地使用数组方法(如 slice),我们需要借助 Array.prototype 上的方法,或者将其转换为真正的数组。例如,可以使用 [...arguments].slice(1)Array.from(arguments).slice(1) 来实现同样的效果。


给你讲的详细点,好理解~ 函数的 arguments 对象并不是一个数组,类似数组具有数字索引和length。只有真正的数组对象才slice方法。 那么通过Array.prototype.slice.call调用,把arguments对象转化为真正的Array对象。 类似下面代码功能 var args = []; for (var i = 1; i < arguments.length; i++) { args.push(arguments[i]); } 一般情况下面2种方法都能实现arguments转数组 var args = Array.prototype.slice.call(arguments); var args = [].slice.call(arguments, 1); 一般情况下arguments.length较小时用var args = [].slice.call(arguments, 1); 性能比较好。 当arguments.length比较大时var args = Array.prototype.slice.call(arguments);性能好。

很好很详细。想了解一下。两个转数组的方式的性能是怎么衡量出来的?我一直以为 [].slice和Array.prototype.slice都是取得同一个function对象,[]是多了一层创建新数组的动作。Array.prototype多了一层对象链搜索。理解布了arguments.length大时,后者的优势在哪。

在Node.js中,arguments对象是一个类数组对象,它包含了函数调用时传入的所有参数。arguments对象本身并不是一个真正的数组,因此它没有数组原型上的方法,比如slice

示例解释

错误的代码

console.log( arguments.slice(1));

这里会报错,因为arguments对象没有slice方法。尝试直接调用arguments.slice(1)会导致TypeError,因为arguments不是真正的数组。

正确的代码

console.log( Array.prototype.slice.call(arguments, 1));

这里使用了Array.prototype.slice.call()来借用数组原型上的slice方法,将arguments对象转换成一个真正的数组,然后执行slice方法。这样可以正确地获取从第二个参数开始的子数组。

示例代码

var invokeCb = function(cb) {
    console.log(Array.prototype.slice.call(arguments, 1)); // 输出 ['bb', 'cc', 'dd']
    console.log( Array.prototype.slice.call(arguments, 1));
}

invokeCb('aa', 'bb', 'cc', 'dd');

总结

由于arguments对象不是真正的数组,直接调用数组方法会失败。通过使用Array.prototype.slice.call(),我们可以将arguments对象转换为真正的数组,并正常调用数组方法。

回到顶部