数组的
map
方法在IE9如下是不支持的,所以须要写一个兼容方法来实现此行为,在实现兼容的时候:必须注意:对于数组中被删除(delete
)或者根本从未赋值的索引项,map
中第一个函数参数是不会执行的。javascript
关于这一点,在ECMA标准和MDN参考文档都是有说明的:html
MDN:
it is not invoked for indexes that are undefined, those which have been deleted or which have never been assigned values.java
ECMA:
callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.数组
我看到一些用来兼容的方法,都没有注意到这种情形,那么不注意这种情形会出现什么问题呢?为何MDN上给的兼容方法会这么曲折呢?浏览器
我先把我在培训班的老师给出的兼容方法贴出来:app
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方法执行上述代码的输出是this
而若是浏览器不支持原生map方法,会执行else语句,这样的输出是:spa
你看,这二者执行区别就在于一开始的结论:原生的map
方法跳过了那些从未赋值的索引对应的项。prototype
简单来讲,对象就是一系列属性名值对,即某个属性名对应某个属性值;当咱们遍历对象时,不在对象中的属性固然不会被访问到。
而在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
属性,且数组中没有跳过的索引),它只是恰好,恰好等于最大的索引加一。当咱们从对象的角度来看待数组时,像0、一、二、三、四、五、6等等这些数字索引和length
同样,都只是数组对象的属性。
用delete
操做符删除数组任意一项,或者将任意一项值赋值为undefined
,length
不改变;
当人为地设置数组的length
属性值时,length
随之改变,同时索引不小于该值的都会被从数组中完全删除。