Javascript 数组越界:与未定义的比较,还是长度检查?
这似乎是一个常见的javascript习惯用法:Javascript 数组越界:与未定义的比较,还是长度检查?,javascript,arrays,Javascript,Arrays,这似乎是一个常见的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'
function foo (array, index) {
if (typeof array[index] == 'undefined')
alert ('out of bounds baby');
}
与更普遍(在其他语言中)和概念上更简单的语言相反:
function foo (array, index) {
if (index >= array.length)
alert ('boo');
}
我知道第一种情况也适用于有“间隙”的数组,但这种情况是否足够普遍,足以证明这种习惯用法的正确性
可以看到提示此问题的代码示例。在这种情况下,当在函数中使用'argument'变量时,假设它将是一个连续数组,这难道不明智吗?唯一正确的方法是检查索引和长度
可以为元素指定值未定义
。在这里当哨兵真是太傻了。(检查未定义可能有其他有效且可能重叠的原因,但不是“检查越界”--当给定arg的值实际上是未定义时,另一个问题中的代码可能会给出错误的结果)
快乐编码。据我所知,这并不常见,更常见的是:
for (var i=0, iLen=array.length; i<iLen; i++) {
// do stuff
}
使用for循环的主要原因是,如果使用for..in循环,数组属性可能不会以数字顺序返回
for..in循环在稀疏数组中效率更高,但如果有问题,则必须处理可能的无序访问(如果应该避免,则必须处理继承的和非数字的可枚举属性)。在这种情况下,测试它以确保它不会意外地将字符串“undefined”添加到调用字符串中。在下面的情况下,它实际上会这样做:
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")
不要测试未定义的。您应该使用数组的长度。在某些情况下,测试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);
如本JSFIDLE所示:您还可以编写:
if (index in array) {
即使array[index]
设置为undefined
,它也将返回true。在JavaScript中,数组可以是稀疏的,它们可以包含“洞”。比如说
const数组=新数组(3);
结果是一个由三个“孔”组成的数组
,而不是值。那么一会儿
const isInBounds=0 index | | index>=array.length
? `索引${index}超出范围`
: !调用(数组、索引)
? `索引${index}是一个洞`
:`index${index}包含${array[index]}`;
控制台日志(msg);
}
const subject=[未定义,1];
显示(主题-1);
//“索引-1超出范围”
对于(设i=0;i
值!==未定义?value.toString():“未定义”;
//因为…当然不会跳过洞
常数byForOf=[];
通过forof.push(toString(value)),for(主体的常量值);
log(`value-find by for..of:${byForOf.join(',')}`);
//为…找到的值:未定义,未定义,1
//.forEach跳洞
常量byForEach=[];
subject.forEach((值)=>byForEach.push(toString(值));
log(`valuesfoundby.forEach:${byForEach.join(',')}`);
//.forEach找到的值:未定义,1
//.减少跳板孔
常数减速机=(acc,值)=>{
acc.push(toString(值));
返回acc;
};
constbyreduce=subject.reduce(reducer,[]);
log(`valuesfoundby.reduce:${byReduce.join(',')}`);
//由找到的值。减少:未定义,1
//.地图保留洞
constbymap=subject.map(toString);
log(`valuesfoundby.map:${byMap.join(',')}`);
//由找到的值。映射:未定义,1
我认为您误解了链接的代码。replace函数可以随机访问arguments数组(一个类似于“{1}{3}{5}{2}”
的字符串就是一个例子),这可能会对传递它的参数产生有趣的影响。我的观点是,这里的检查不是检查数组的边界,而是检查是否存在,并在命名属性未定义时提供回退。99%的情况下,您希望对照length
属性进行检查,链接的代码是少数不检查的情况之一。此外,测试应该是if(index
,因为长度总是比上一个索引多一个,并且array[array.length]
总是未定义。作为练习,尝试执行以下代码:var arr=[];arr[5]=2代码>。执行第一个循环,您将立即在索引0处得到一条越界消息,但是arr.length将正确地告诉您,arr
有6个元素。这并不总是有效的——尽管我相信它在参数
的情况下总是有效的,因为JavaScript中的数组是“稀疏的”。这就是为什么(数组中的v){…}
有时会出现问题的原因。(有一个未定义的值和一个未设置的索引是有区别的,这两个值都适用于和未设置的索引。例如,考虑<代码> var a= [];a[1]=“foo”;a
中的0将导致false。a
中的数组有自己的属性“1”和“length”,但它没有名为“0”的属性。
4
undefined
foo
if (index in array) {