Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

JavaScript拟数组的概念

  之前的文章中也吐过何谓数组这类问题,当时的看法是[[Prototype]]比[[Class]]更重要。现在觉得,原型又算什么,只要有length属性的,不都可以遍历,不都具有数组的性质吗?如果再结合ES6的可迭代对象来考虑的话,整个概念就又被扩充了一圈。
  我们经常会将arguments作为apply的参数,但arguments确实不是个数组,无论是[[Class]]还是[[Prototype]],它都不是数组。唯一能让它看起来像数组的就是它具有length属性(甚至这个length属性都是configurable的,可以随意地删除它)。也就是说,这种奇葩对象都能作为apply的第二个参数了,还也有什么对象不可以的呢?
<script>
function f(){ console.log(arguments); };
//只要有length属性,随便一个对象都可以
f.apply(null,{0:"拟数组项1",1:"拟数组项2",length:2});
//甚至字符串对象也有拟数组的性质
f.apply(null,Object("次碳酸钴"));
</script>
  在ES6中的迭代器也是一个可遍历的东西,只是它不是通过length来遍历,所以无法直接作为拟数组来使用。但是可以通过“...”语法将其转换为序列。 <script>
//请使用Firefox测试
function f(){ console.log(arguments.length); };
function*g(){ for(var i=0;i<10;i++)yield i; };
//由于没有length,所以arguments接收不到东西
f.apply(null,g()); //0
//使用数组字面量的“...”语法可以将其转换为数组
f.apply(null,[...g()]); //10
//直接在调用中使用“...”语法也可以
f(...g()); //10
</script>
  之前的拟数组对象,也可以通过迭代器来转换,只要让其调用数组原型的迭代器即可 <script>
var arrayLike={0:"拟数组项1",1:"拟数组项2",length:2};
//注意:Chrome 使用 Array.prototype[Symbol.iterator] 来访问数组迭代器
//但是 Chrome 暂不支持 “...” 语法,这个代码请在 Firefox 上测试
console.log([...Array.prototype["@@iterator"].call(arrayLike)]);
</script>
  至此,我们就有了一个概念,所有对象都可以转换成数组,对于不可迭代对象也可以使用数组迭代器来将其转换成数组。然而,ES6并没有给对象添加一个“toArray”之类的属性,但是反过来直接在数组构造器上添加了Array.from方法,概念基本是相同的。于是我们不用写上面那么麻烦的代码,直接使用这个就可以做到同样的效果。
<script>
var arrayLike={0:"拟数组项1",1:"拟数组项2",length:2};
//Chrome 暂不支持 Array.from,这个代码请在 Firefox 上测试
console.log(Array.from(arrayLike));
</script>
  当然,Array.from的功能不止这个,这里就不介绍了。
  也许以后判断是否具有数组性质的代码会依赖length属性,所以还在滥用length属性的请自重了!
网名:
3.80.32.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^