这似乎是一个常见的javascript惯用语:
function foo (array, index) {
if (typeof array[index] == 'undefined')
alert ('out of bounds baby');
}
而不是更普遍(在其他语言中)和概念上更简单:
function foo (array, index) {
if (index >= array.length)
alert ('boo');
}
据我所知,第一种情况也适用于其中有“缺口”的数组,但这是一个足以保证成语的常见情况吗?
可以看到提示此问题的代码示例here。在这种情况下,当在函数内部使用'argument'变量时,假设它是一个连续的数组是不是很明智?
答案 0 :(得分:26)
唯一正确的方法是检查索引与长度。
可以为元素分配值undefined
。在这里使用它作为哨兵只是愚蠢。 (可能存在检查未定义的其他有效且可能重叠的原因,但不是“对于超出限制的检查” - 当给定arg的值为真的 undefined
。)
快乐的编码。
答案 1 :(得分:15)
你也可以写:
if ( index in array ) {
即使array[index]
设置为undefined
,也会返回true。
答案 2 :(得分:1)
不要测试undefined。您应该使用数组的长度。有些情况下,它根本无法测试未定义,因为undefined是合法数组条目的合法值。这是一个合法的JS数组:
var legalArray = [4, undefined, "foo"];
你可以像这样访问它:
var legalArray = [4, undefined, "foo"];
var result = "";
for (var i = 0; i < legalArray.length; i++) {
result += legalArray[i] + "<br>";
}
$("#result").html(result);
生成此输出:
4
undefined
foo
如本jsFiddle所示:http://jsfiddle.net/jfriend00/J5PPe/
答案 3 :(得分:0)
据我所知,这并不常见,更常见的是:
for (var i=0, iLen=array.length; i<iLen; i++) {
// do stuff
}
您不应该与undefined进行比较,因为数组的成员可能已被赋值为undefined
,或者可能未分配任何值。
e.g。
var a = [0,,,,];
alert(a.length); // 4 (or 5 in buggy IE);
a[1] === undefined; // true but not out of bounds
使用for循环的主要原因是,如果使用for..in循环,则数组属性可能不会以数字顺序返回。
for..in循环在稀疏数组中效率要高得多,但是如果重要的话必须处理可能的无序访问(如果应该避免,则必须继承和非数字可枚举属性)。 / p>
答案 4 :(得分:0)
在 JavaScript 中数组可以是稀疏的——它们可以包含“洞”。例如
const array = new Array(3);
导致 array
三个“洞” - 不是值。所以同时
const isInBounds = 0 <= index && index < array.length;
正确识别 index
是否在 array
的边界内,但不指示 array[index]
处是否有值。
Object.prototype.hasOwnProperty()
可用于确定值是否存在于 index
。还需要注意的是,在存在“漏洞”的情况下,语言的不同部分可能表现得非常不同。
// ESLint: no-prototype-builtins)
const hasOwnProperty = Object.prototype.hasOwnProperty;
function show(array, index) {
const msg =
0 > index || index >= array.length
? `index ${index} is out of bounds`
: !hasOwnProperty.call(array, index)
? `index ${index} is a hole`
: `index ${index} holds ${array[index]}`;
console.log(msg);
}
const subject = [undefined, , 1];
show(subject, -1);
// "index -1 is out of bounds"
for (let i = 0; i < subject.length; i += 1) show(subject, i);
// "index 0 holds undefined"
// "index 1 is a hole"
// "index 2 holds 1"
show(subject, 3);
// "index 3 is out of bounds"
const toString = (value) =>
value !== undefined ? value.toString() : 'undefined';
// for..of doesn't skip holes
const byForOf = [];
for (const value of subject) byForOf.push(toString(value));
console.log(`Values found by for..of: ${byForOf.join(', ')}`);
// "Values found by for..of: undefined, undefined, 1"
// .forEach skips holes
const byForEach = [];
subject.forEach((value) => byForEach.push(toString(value)));
console.log(`Values found by .forEach: ${byForEach.join(', ')}`);
// "Values found by .forEach: undefined, 1"
// .reduce skips holes
const reducer = (acc, value) => {
acc.push(toString(value));
return acc;
};
const byReduce = subject.reduce(reducer, []);
console.log(`Values found by .reduce: ${byReduce.join(', ')}`);
// "Values found by .reduce: undefined, 1"
// .map preserves holes
const byMap = subject.map(toString);
console.log(`Values found by .map: ${byMap.join(', ')}`);
// "Values found by .map: undefined, , 1"
答案 5 :(得分:-1)
在这种情况下,测试它以确保它不会意外地将字符串“undefined”添加到调用String。在下面的例子中,它实际上会这样做:
var undefd;
"{0} is dead, but {1} is alive! {0} {2}".format("ASP", undefd, "ASP.NET")
// output as "ASP is dead, but {1} is alive! ASP ASP.NET"
就个人而言,我可能只是缓存长度,然后进行数字比较。
旁注:他的方法也避免了NaN检查,但强制严格并行:
// this will fail unless 0001 is cast to a number, which means the method
// provided will fail.
"{0} is dead, but {1} is alive! {0001} {2}".format("ASP", "ASP.NET")