繁体   English   中英

为什么JavaScript不会为此代码示例引发异常?

[英]Why does JavaScript not throw an exception for this code sample?

我希望人们能原谅我一个相当基本的JavaScript问题(对我而言,这通常不是“主要”语言)。 我正在查看W3Schools的JavaScript教程进行审查; 他们关于数组课程具有以下警告和代码示例:

警告:添加具有高索引的元素会在数组中创建未定义的“孔”:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits[6] = "Lemon"; // adds a new element (Lemon) to fruits

这将导致索引4和5包含undefined

此外,我可以做类似alert(fruits[20]); (这使我弹出一个窗口,说“未定义”)无一例外。

在大多数对键入更为严格的语言中,尝试执行这些操作之一将导致运行时异常。 我确实意识到我们这里没有一个人在JavaScript设计委员会中(据我所知),但是没有人知道为什么允许这些(例如,为什么他们不抛出运行时异常或类似的东西)?

我可以理解做诸如fruits[4] = "Lemon" (因为它本质上是追加到数组中),但是有没有合理的理由去做诸如fruits[6] = "Lemon"类的事情呢?

似乎也像在做alert(fruits[20]); 几乎总是会指出一个错误-实际上,我想不出任何合法的用例。 这个对吗?

这个问题的答案中我的理解是,JavaScript数组“实际上更像是将属性用作索引的自定义对象”,而不是Java或C#中的数组。 答案之一也指出

Javascript数组不是真正的数组,例如C / C ++或其他语言。 因此,它们没有那么高效,但是可以说它们更易于使用并且不会超出范围。

这些说法正确吗? 这是JavaScript中这种行为的原因吗?

JavaScript不会将访问不存在的数组元素和对象属性视为错误。 当代码尝试进行这些访问时,它仅返回undefined

一些常见的习语利用了这一点。 你可以写:

var fruit20 = fruits[20] || defaultFruit;

由于undefined为falsey,因此它不存在时将返回defaultFruit 这比以下简单:

var fruit20 = '20' in fruits ? fruits[20] : defaultFruit;

通常,您会从尝试使用结果值的代码中得到一个错误。 例如,如果您这样做:

var firstLetter = fruits[20].substr(0, 1);

由于尝试访问undefinedsubstr属性,它会发出异常信号,因为undefined没有任何属性。

在C或具有“真”数组(即,连续内存中的指针序列)的另一种语言中,越界写操作可能会破坏正在运行的程序甚至另一个进程。

JavaScript的Array可以动态调整大小,因此没有非法访问或损坏的风险。

通常,JavaScript仅在没有其他选择时才会抛出运行时异常。 在这种情况下,还有一种选择-动态调整数组的大小-因此它更喜欢抛出。

我看到您说的不是您的主要语言...所以我将与c ++进行比较

在c ++中,您声明了一部分内存: int a[50]; //系统为我们重新解析了50 * sizeof(int)的一部分,我们可以在其中执行所需的操作。 a是第一个int的指针

例如: cout<<a[20] ; //将返回存在的内存中的变量,它是我们的内存部分,即使我们没有提早设置它也是如此。 cout<<a[51] //错误...为什么?...,因为该程序将尝试访问我们没有访问权限(或操作系统未授予权限)的地址;

在js中,您可以执行以下操作:console.dir(fruits); ...您会在其中看到很多功能,...甚至您在水果中没有说过的“ length”属性也可以用来设置length属性吗?... js中的基本数组是c ++中的一个类

在c ++中,当您引用数组时,您引用的是指针A的内存+数组类型的大小:

示例: cout<<*A ; //与cout<<A[0]; or cout<<*(A+0); cout<<*(A+5) ; //与cout<<A[5];

A [5] = *(A + 5)= *(5 + A)= 5 [A]

所以

for(int i=0; i<n; i++)
   cout<<i[A];

//与cout<<A[i] ..疯了吧?

在回答您的问题时,首先进行演示:

 var a = []; console.log( "initial length is: " + a.length); a[1.5] = 1.5 console.log( "a[1.5] is " + a[1.5] + ", length is " + a.length); a["foo"] = "bar"; console.log( "a.foo is " + a.foo + ", length is " + a.length); a[-1] = -1; console.log( "a[-1] is " + a[-1] + ", length is " + a.length); a[10] = "item 10"; console.log( "a[10] is " + a[10] + ", length is " + a.length); a[20] = "item 20"; console.log( 'a[ 20 ] is ' + a[ 20 ] + ", length is " + a.length); console.log( 'a["20"] is ' + a["20"] + ", length is " + a.length); console.log( 'a["0x14"] is ' + a["0x14"]); console.log( "a.hasOwnProperty( 20) " + a.hasOwnProperty( 20)); console.log( "a[ 15] " + a[ 15]); console.log( "a.hasOwnProperty( 15) " + a.hasOwnProperty( 15)); a[15] = undefined; console.log( "a[ 15] " + a[ 15]); console.log( "a.hasOwnProperty( 15) " + a.hasOwnProperty( 15)); 

  • JavaScript中的数组被认为是外来对象。 除了使用非负整数数值设置属性时,它们的行为均与普通对象相同。
  • 数组由全局Array构造函数构造,并从Array.prototype继承方法。
  • length属性保持为数组中包含的最高非负整数属性(这是奇异部分)的一倍以上。
  • 元素的索引和值都存储在数组中。 数字索引将转换为基数10格式的字符串值,用作元素的(对象)属性名称。 尽管在代码中不常见,但您可以将a[20]引用为a["20"] 您不能引用与a["0x14"]相同的元素,因为属性字符串名称“ 0x14”不存在。
  • and数组的技术名称为“稀疏数组”。
  • 稀疏数组不包含缺少元素的undefined值。 尝试查找不存在的元素时,返回undefined (这与查找不存在的对象属性时的行为相同。)
  • 由于undefined是原始值,因此可以将数组元素设置为undefined 现在该元素存在,而不是找不到。
  • 为什么将JavaScript数组称为“关联”的一种解释是,它们不为未设置的数组内容保留内存。 当访问带有有效数字索引的元素时,他们可能必须搜索属性名称列表,而不必说出可能的搜索类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM