资讯专栏INFORMATION COLUMN

JavaScript中“数组也是对象”

Sike / 2267人阅读

摘要:数组也是对象简单来说,对象就是一系列属性名值对,即某个属性名对应某个属性值当我们遍历对象时,不在对象中的属性当然不会被访问到。我们知道操作符用于删除对象中某个属性,而中,数组就是对象的一种,数组的索引就是其属性名,对应的项就是属性值。

先说结论吧:
  

数组的map方法在IE9以下是不支持的,因此需要写一个兼容方法来实现此行为,在实现兼容的时候:必须注意:对于数组中被删除(delete)或者根本从未赋值的索引项,map中第一个函数参数是不会执行的。

关于这一点,在ECMA标准和MDN参考文档都是有说明的:

  

MDN:
it is not invoked for indexes that are undefined, those which have been deleted or which have never been assigned values.

  

ECMA:
callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.

我看到一些用来兼容的方法,都没有注意到这种情形,那么不注意这种情形会出现什么问题呢?为什么MDN上给的兼容方法会这么曲折呢?

我先把我在培训班的老师给出的兼容方法贴出来:

javascriptArray.prototype.myMap = function (fn, context) {
    context = context || window;
    var ary = [];
    if (Array.prototype.map) {
        ary = this.map(fn, context);
    } else {
        for (var i = 0; i < this.length; i++) {
            ary[i] = fn.apply(context, [this[i], i, this]);
        }
    }
    return ary;
}

这个实现比较简单,流程很清晰,如果浏览器有原生数组map方法,调用该方法,否则执行else中的语句;但是如果是下面这样一个数组,在没有实现原生map方法的浏览器中,结果跟原生map方法调用不一样:

javascriptvar arr=[1,2,,,3];
console.dir(arr.myMap(function(e,i,a){return e*2;}));

原生map方法执行上述代码的输出是

而如果浏览器不支持原生map方法,会执行else语句,这样的输出是:

你看,这两者执行区别就在于一开始的结论:原生的map方法跳过了那些从未赋值的索引对应的项。

数组也是对象!!

简单来说,对象就是一系列属性名值对,即某个属性名对应某个属性值;当我们遍历对象时,不在对象中的属性当然不会被访问到。

而在JS中,数组就是对象,甚至数组的一些遍历方法,在内部执行的时候,都是先将数组转化为对象,

javascriptvar O=Object(this);

然后遍历数组对象中,所有已经定义的,且索引为数字的项。在绝大部分情况下,这些数字刚好是连续的。那什么时候会出现不连续呢?我所知道有这两种;

以字面量方式新创建数组的时候,连续的逗号,会形成数字索引不连续;如var arr=[1,2,,,3],你可以在浏览器控制台中试试输出console.dir([1,2,,,3])的结果(注意,一定要用console.dir方法);

利用delete操作符删除数组中的某项。我们知道delete操作符用于删除对象中某个属性,而JS中,数组就是对象的一种,数组的索引就是其属性名,对应的项就是属性值。用delete删除后,数组中的这对属性名值对(又称键值对)就不存在了,这时候对其采用遍历方法,当然不会针对不存在名值对进行调用了。

有一点要特别注意,数组中被删除的项或者从未定义的项,与人为将其值设置为undefined的项,尽管如果强行访问,结果都是undefined,但是是不太一样的,比如这样一个数组,[1,,undefined];,该数组(现在我们可以更准确得说:数组对象)中不存在索引为1的项,但是却存在索引为2的项,可以用console.dir输出看出区别。 数组的length属性还能反映数组长度吗?

说到上面这些,你肯定已经意识到了,既然数组的索引可以被跳过,那数组的length属性还能反映其长度吗?

关于这个问题,我是这么理解的,

数组的length属性并不能反应数组中元素的数目,在绝大多数情况(即没有人工干预length属性,且数组中没有跳过的索引),它只是刚好,刚好等于最大的索引加一。当我们从对象的角度来看待数组时,像0、1、2、3、4、5、6等等这些数字索引和length一样,都只是数组对象的属性。

delete操作符删除数组任意一项,或者将任意一项值赋值为undefinedlength不改变;

当人为地设置数组的length属性值时,length随之改变,同时索引不小于该值的都会被从数组中彻底删除。

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

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

相关文章

  • JavaScript学习笔记之数组(一)

    摘要:数组基础篇数组的语法数组是按次序排列的一组值。属性数组的属性,返回数组的成员数量。通过设置的值改变数组的长度将属性设为可以清空数组。类似数组的对象并不是数组,因为它们不具备数组特有的方法。 数组基础篇 1.数组的语法 数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始)。var arr=[1,2,3] //arr[0]=1任何类型的数据,都可以放入数组。 var ...

    Yangder 评论0 收藏0
  • JavaScript语言精粹 修订版》 读书笔记

    摘要:于是我就先把这本薄的经典书语言精粹修订版豆瓣读书本书简介总共章,除去附录,才页,读完并记录了一些笔记。读书笔记还可以分享给别人看。编程语言第版定义了的标准。程序检查时丢弃值为函数的属性。 之前看到这篇文章,前端网老姚浅谈:怎么学JavaScript?,说到怎么学习JavaScript,那就是看书、分析源码。10本书读2遍的好处,应该大于一本书读20遍。看书主动学习,看视频是被动学习。看...

    EscapedDog 评论0 收藏0
  • ES5学习(上)

    摘要:对象是一个值超出有效范围时发生的错误。包括返回原数组包括数组对象函数可以用来判断变量是否为对象数组对象函数构造函数与直接赋值是等价的。只适用于,数组不适用通过可以看出一个值到底是什么类型,其中返回值的第二个值表示该值的构造函数。 这是ES5的入门篇教程的笔记,网址:JavaScript教程,以下内容中黑体表示大标题,还有一些重点;斜体表示对于自身,还需要下功夫学习的内容。这里面有一些自...

    HackerShell 评论0 收藏0
  • javascript高级程序设计》笔记_数组 稀疏数组数组

    摘要:数组是数据的有序列表,与其他语言不同的是,数组的每一项可以保存任何类型的数据。如下的代码创建的就是一个密集数组稀疏数组与密集数组相反,并不强制要求数组元素是紧密相连的,即允许间隙的存在。 数组是数据的有序列表,与其他语言不同的是,ECMAScript 数组的每一项可以保存任何类型的数据。也就是说,可以用数组的第一个位置来保存字符串,用第二位置来保存数值,用第三个位置来保存对象, 以此类...

    pepperwang 评论0 收藏0
  • JavaScript入门】Array类型

    摘要:数组也是对象数据类型的数组也有属性名,只不过属性名是数字,我们把数字属性名称之为它的索引数组是以数字作为索引,索引从零开始,有一个属性代表数组的长度。 Array 数组也是对象数据类型的 typeof [] ->object数组也有属性名,只不过属性名是数字,我们把数字属性名称之为它的索引:数组是以数字作为索引,索引从零开始,有一个length属性代表数组的长度。 showImg(h...

    zxhaaa 评论0 收藏0

发表评论

0条评论

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