开工第一天,后面的老王同志就抛出了一个让我很懵逼的问题。正好没啥子事,我就扒了一扒,学习一下基础知识。于是有了一些收获,感谢老王同志。
题目:
- 模拟代码
var a = [];
a.length = 2;
console.log(a.indexOf(undefined)); // 此处打印出 -1
- 问题:
已知,a[0] === undefined,
为什么 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
。我自己理解这两句体现的要点如下:
- 查询的范围和key值获取结果有关;
- 判断数组中的元素是否为undefined,判断索引是否合法或索引对应的元素是否在数组中。
关于 in 算法,我找到如下解释,可以帮助理解:
- 如果右边是数组左边是数字,会把左边的数字 (字符串形式的也可以如 "2" in arr 等于 2 in arr)当成一个索引去检查,如果索引是合法的就返回true。
- 如果右边是数组左边是字符串 比如"id",会把左边的值当成一个属性去检查,如果找到该属性就返回true。
- 如果右边是对象这个时候不管左边字符串还是数字,会把左边的值当成一个属性去检查,如果找到该属性就返回true。
经验证,在数组未赋值的时候拿不到key值。
查询 key 值
Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in
循环遍历该对象时返回的顺序一致 。
- 语法
Object.keys(obj)
-
参数
obj
要返回其枚举自身属性的对象。 -
返回值
一个表示给定对象的所有可枚举属性的字符串数组。 -
相关描述
Object.keys 返回一个所有元素为字符串的数组,其元素来自于从给定的 object 上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致。
如果想获取一个对象的所有属性,甚至包括不可枚举的,可使用 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 这个值时,未赋值的元素没有索引属性,无法查到值。
欢迎补充和指正
网友评论