资讯专栏INFORMATION COLUMN

Javascript数组不完全解析

lscho / 2365人阅读

摘要:关于数组的遍历,的方式相对于等语言是很奇怪的打印结果可以看到,打印的结果不是数组的元素,而是数字索引值感觉这好像也可以说明,的数组也是用的方式存储的,不管怎样,这一点要注意。

上一篇说了数组的索引,这一篇说下数组的使用。

数组的大小

js的数组可以动态调整大小,更确切点说,它没有数组越界的概念,a[a.length]没什么问题。比如声明一个数组a = [1, 3, 5],现在的数组大小是3,最后一个元素的索引是2,但是你依然可以使用a[3],访问a[3]返回的是undefined,给a[3]赋值:a[3] = 7,是给数组a添加了一个元素,现在数组a的长度是4了。你可以试试把下面这段代码放到浏览器里运行下:

    var a = [];
    for(int i = 0; i <= a.length; i++)
    {
        a[a.length] = i;
    }

在我的电脑上,火狐会立马崩掉,chrome这一个标签cpu占用99%(使用chrome的任务管理器查看的)。

js的length的值会随着数组元素的改变而改变,当然你也可以手动设置数组的 length 属性,设置更大的length不会给数组分配更多的空间,但是设置更小的length则会导致所有下标大于等于新length的属性被删除。

另外有一点就是,数组的length值是怎么来的,有的资料说是最大一个数字索引值加一,应该是对的,不过如果把空槽也算数的话,length值就是数组的元素数。上张图解释下:

从图里可以看到,有个数组a,a[0]a[10]都已赋值,这时候a的length是11,中间有9个empty slot(姑且就翻译为空槽好了)。那这九个空槽算不算数呢,我觉得应该算,这样就能合理的解释length值了。那这些空槽的值是什么呢?undefined!所以呢,如果在chrome里,使用foreach遍历(forin),那么这些空槽正好都能跳过,而使用for遍历,则会打印出undefined。至于在firefox里,表现不太一样,自己试吧。

数组的遍历

昨天在看微博上转的js教程的时候,里面说在遍历数组的时候,判断语句i会造成每循环一次都要计算一次长度,从而对性能有一点点影响。这一点我表示疑问,我不确定到底是不是这样,而且不同的浏览器对这种情况可能还有不同的优化,我在网上搜了下,找到了几个网页说了要缓存数组大小,但是都是抄的,没主见,也没说明原理,所以我表示很怀疑,而且我在chrome测试了下,性能上没什么明显差异。关键是我觉得,length是个数组的属性,每次调用a.length的时候,只是访问这个属性而已,属性都是用hash的方式存储的,所以访问的时间复杂度是O(1)。这是我的看法,如果不对,请告诉我。

关于数组的foreach遍历,js的方式相对于java/c#等语言是很奇怪的:

        for(var name in ["huey", "dewey", "louie"]) {
            console.log(name);
        }
        /*
            打印结果:
            0
            1
            2
        */

可以看到,打印的结果不是数组的元素,而是数字索引值(感觉这好像也可以说明,js的数组也是用hash的方式存储的),不管怎样,这一点要注意。(至于为什么这样,我觉得数组元素都是数组的属性,这个遍历是遍历的length值,从0到length。而不是逐个输出数组的元素,因为元素是属性,数组又不只数字索引这一种属性,那么为什么这样遍历的时候只输出它们呢,而不是length,push,join等方法?公平起见,只好输出数组的数字索引了。当然,这只是我自己的看法,具体怎么样我没研究。)

数组的一些方法

数组有pushpop方法,这样数组就像堆栈一样了。对数组使用delete,可以将数组中某个元素移除,但是那样会在数组中留下一个空洞(也就是说delete也可以删除数组中的元素,但是只是删除该位置的值,不改变数组大小,原位置类型是undefined),这是因为排在被删除元素之后的元素保留着它们最初的属性,所以应该使用splice对进行过delete操作的数组进行瘦身,它会将被删除的属性移除,但这样效率并不是很高。数组中还有mapreducefilter等方法,这里就不多说了(跟python中的list挺像的)。

补充

最后补充一点,我前面说过,js中的数组就是对象(废话,本来就是对象),那么是不是说,数组和对象可以互相互替换着用呢?答案是可以的。不过为了明确,还是分开用比较好,下面说下什么时候该用数组,什么时候该用对象(参考《javascript语言精粹》):

  

当属性名是小而连续的整数时,应该使用数组,否则,使用对象。
另外由于js中对数组和对象使用 typeof 的结果都是 Object,因此判断一个对象是否为数组的方法:

    var is_array = function(value) {
    return Object.prototype.toString.apply(value) === "[object Array]";
    };
番外

觉得闭包被神化了,可能语言层面上的实现有技术,但是在应用层面我觉得就应该那样啊,使用的时候都感觉不到那是在用闭包。但是这个闭包却几乎成了面试前端必问的概念了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85755.html

相关文章

  • Javascript数组索引完全解析

    摘要:数组的大小是不固定的,可以像这样随意添加。再看一张图,这次多添加几个元素,再给数组添加一个属性注意看右侧对象的元素索引不知道你有没有发现。数组范围和索引转换那里是参考的,其他地方都是自己的理解和看法。 从题目说起,之所以是不完全,是因为有些东西比如数组的方法怎么用这个我都不打算讲,因为那个看一下都会,下面讲的都是我觉得重要的,只关于数组对象本身。另外,由于我的Javascript实战经...

    levius 评论0 收藏0
  • 【译】使用"BinaryAST"加快JavaScript脚本的解析速度?

    摘要:是提出并积极开发的一种新的在线格式,旨在加快解析速度,同时保持原始的语义不变。它的实现方式是使用有效的二进制来表示代码和数据结构,并且存储和提供额外的信息来提前指导解析器工作。提升依赖于提升所有声明变量函数类。 原文:Faster script loading with BinaryAST?本文首发于公众号:符合预期的CoyPan JavaScirpt的冷启动 web应用的表现,越来...

    Hujiawei 评论0 收藏0
  • JSON数据格式的使用

    摘要:数据格式是一种轻量级的数据交换格式。为了对名为的对象进行转换,只需执行相同形式的命令这就是与本系列讨论的其他数据格式之间最大的差异。不过,我们读起来费解的语言,恰恰是适合机器阅读,所以通过的索引就能够读取黑龙江这个值。 JSON 数据格式 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON采用完全独立于语言的文本格式,这些特性使...

    番茄西红柿 评论0 收藏0
  • 哎哟,这就是JSON

    摘要:官方的说法,也不是特别的明了,只说明了这是一种轻量级的数据交换格式,且基于一个子集。的语法介绍常见数据结构有两种形式,其分别是名称值对的集合,类似中的对象。比如,则在中是行不通的。 写这篇文章的缘由 你了解JSON嘛?JSON是JavaScript中对象嘛?JSON可以存储function对象嘛?JSON的本质是什么呢?JSON能写注释嘛? 如果你都能答上来,那恭喜你,你对JSON了...

    邱勇 评论0 收藏0
  • 完爆Facebook/GraphQL,APIJSON全方位对比解析(三)-表关联查询

    摘要:相关阅读完爆,全方位对比解析一基础功能完爆,全方位对比解析二权限控制自发布以来,不断有网友拿来和的对比,甚至有不少人声称完爆。近年稳步上升,已跃居第名。 相关阅读: 完爆Facebook/GraphQL,APIJSON全方位对比解析(一)-基础功能 完爆Facebook/GraphQL,APIJSON全方位对比解析(二)-权限控制 自APIJSON发布以来,不断有网友拿来和Facebo...

    Jioby 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<