簡體   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