Array.prototype.slice.call(arguments) 到底做了什么?

Array.prototype.slice.call(arguments) 到底做了什么?

如题,在一些代码中我们经常会看到Array.prototype.slice.call(arguments) 或者[].slice.call(arguments)这段代码,那这段代码到底做了什么呢?我们就来探寻一下

问题

首先来看一段代码:

function foo() {
	console.log(arguments)
	console.log(Array.prototype.slice.call(arguments))
}
foo(1,2,3)

在这个 foo 函数中我们打印了 arguments 以及我们经常看到的这段代码Array.prototype.slice.call(arguments),那它们的结果肯定大家都知道:

foo(1,2,3); 
// {0:1,1:2,2:3,length:3}
// [1,2,3]

大概是这样的,而且我们也知道arguments是一个array-like(类数组)对象,具体解释可以在MDN查看 ,那为什么经过了上述代码之后就变成了真正的数组了呢?

具体解释

我们首先来明确一个事情,就是当你通过

object.method()

来使用一个方法的时候,object自动成为当前方法methodthis值,所以当像如下代码那样使用slice()方法的时候:

[1,2,3].slice()

[1,2,3]自动变成了slice()方法的this.这个是程序定义的,我们如果想要修改,就需要使用 call 或者apply或者bind(他们之间的区别请看todo),这里我们使用 call来演示:

[1,2,3].slice.call([2,3,4]) //[2,3,4]
// 这样写是无意义的只是作为call的展示

那么回到问题上来,我们知道arguments是个类数组对象了,如果将它作为 slice()this值,程序会如何处理呢?
在这里,slice 方法会认为类数组对象已经满足它自身运行的需要(有length属性,有数字作为key的键值对),所以 slice方法会正常运行,然后得到的结果就是返回一个真正的数组对象。

引申

如果我们将 arguments 改为其他的值,那么会发生什么呢?

Array.prototype.slice.call(123);    // []
Array.prototype.slice.call("123");    // ["1", "2", "3"]
Array.prototype.slice.call(true);   // []
Array.prototype.slice.call(null);   // error
Array.prototype.slice.call(undefined);  // error 
Array.prototype.slice.call({foo:"foo",bar:"bar",length:2});     // [empty × 2]

那除了这样的方式将一个其他类型的值转化为数组还有没有其他简便的办法呢?(在函数中)
我们就可以使用 es6 中的 ...rest参数了:

function bar(...rest) {
	console.log(rest)
}
bar()   // []
bar(1,2,3)  //[1,2,3]
// 下面的两种方式也是可行的
function baz() {
	console.log(Array.from(arguments))
	console.log([...arguments])
}
baz(3,4,5)

推荐在以后的函数中使用 ...rest参数来替换 arguments局部参数。

扫描二维码关注公众号,回复: 9650046 查看本文章

总结

Array.prototype.slice.call(arguments)可以使一些类数组对象转换为对象,从而使用数组的方法来解决一些问题。

发布了37 篇原创文章 · 获赞 12 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/peng_9/article/details/102505250
今日推荐