引用类型 Array 的实践探索

2019-02-12  本文已影响0人  爆发吧小宇宙
《飞驰人生》之去热带岛屿游泳

开工第一天,后面的老王同志就抛出了一个让我很懵逼的问题。正好没啥子事,我就扒了一扒,学习一下基础知识。于是有了一些收获,感谢老王同志。

题目:

var a = [];
a.length = 2;
console.log(a.indexOf(undefined)); // 此处打印出 -1

indexOf() 方法源码

题目一看,有点懵,第一反应也是去查源码,搜了一会子,找到如下片段:

// For .indexOf, we don't need to pass in the number of arguments
// at the callsite since ToInteger(undefined) == 0; however, for
// .lastIndexOf, we need to pass it, since the behavior for passing
// undefined is 0 but for not including the argument is length-1.
function InnerArrayIndexOf(array, element, index, length) {
  if (length == 0) return -1;
  if (IS_UNDEFINED(index)) {
    index = 0;
  } else {
    index = TO_INTEGER(index);
    // If index is negative, index from the end of the array.
    if (index < 0) {
      index = length + index;
      // If index is still negative, search the entire array.
      if (index < 0) index = 0;
    }
  }
  var min = index;
  var max = length;
  if (UseSparseVariant(array, length, IS_ARRAY(array), max - min)) {
    %NormalizeElements(array);
    var indices = %GetArrayKeys(array, length);
    if (IS_NUMBER(indices)) {
      // It's an interval.
      max = indices;  // Capped by length already.
      // Fall through to loop below.
    } else {
      if (indices.length == 0) return -1;
      // Get all the keys in sorted order.
      var sortedKeys = GetSortedArrayKeys(array, indices);
      var n = sortedKeys.length;
      var i = 0;
      while (i < n && sortedKeys[i] < index) I++;
      while (i < n) {
        var key = sortedKeys[I];
        if (!IS_UNDEFINED(key) && array[key] === element) return key;
        I++;
      }
      return -1;
    }
  }
  // Lookup through the array.
  if (!IS_UNDEFINED(element)) {
    for (var i = min; i < max; i++) {
      if (array[i] === element) return I;
    }
    return -1;
  }
  // Lookup through the array.
  for (var i = min; i < max; i++) {
    if (IS_UNDEFINED(array[i]) && i in array) {
      return I;
    }
  }
  return -1;
}

看来看去,这里面看不出答案,比较关键的一句就是var indices = %GetArrayKeys(array, length);IS_UNDEFINED(array[i]) && i in array。我自己理解这两句体现的要点如下:

关于 in 算法,我找到如下解释,可以帮助理解:

  1. 如果右边是数组左边是数字,会把左边的数字 (字符串形式的也可以如 "2" in arr 等于 2 in arr)当成一个索引去检查,如果索引是合法的就返回true。
  2. 如果右边是数组左边是字符串 比如"id",会把左边的值当成一个属性去检查,如果找到该属性就返回true。
  3. 如果右边是对象这个时候不管左边字符串还是数字,会把左边的值当成一个属性去检查,如果找到该属性就返回true。

经验证,在数组未赋值的时候拿不到key值。

查询 key 值

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。

Object.keys(obj)

如果想获取一个对象的所有属性,甚至包括不可枚举的,可使用 Object.getOwnPropertyNames

从上述关于获取 key 的内容来看,可以推测,我们的数组中是找不到未赋值的索引属性的,所以才会找不到。

我看了在《JavaScript高级程序设计》一书中找到了关于array的篇章,对array也有了更深的理解。贴图如下,供大家参考:


JavaScript高级程序设计-引用类型-arra�y
JavaScript高级程序设计-引用类型-array-1
JavaScript高级程序设计-引用类型-array-2
JavaScript高级程序设计-引用类型-array-3
JavaScript高级程序设计-引用类型-array-4

我自己理解如下:
在js语言中,数组实际上是一个对象,有一些固定的属性如:length 等,当给数组增加元素的时候,比如执行 a[0] = 222 这个操作,会在数组的属性中增加键值对(用json表示) {'0': 222},这样数组就会多了一个由索引生成的属性 ‘0’。对于未赋值的数组的元素,值为 undefined,通过 indexOf 方法查找是否包含 undefined 这个值时,未赋值的元素没有索引属性,无法查到值。

欢迎补充和指正

上一篇 下一篇

猜你喜欢

热点阅读