淺談Javascript數(shù)組索引
從題目說起,之所以是不完全,是因?yàn)橛行〇|西比如數(shù)組的方法怎么用這個(gè)我都不打算講,因?yàn)槟莻€(gè)看一下都會,下面講的都是我覺得重要的,只關(guān)于數(shù)組對象本身。另外,由于我的Javascript實(shí)戰(zhàn)經(jīng)驗(yàn)不多,所以可能有些東西沒涉及到,有些內(nèi)容說的有誤,請發(fā)現(xiàn)問題的同學(xué)不吝指教。
首先,Javascript(下稱js)的數(shù)組定義,這不是重點(diǎn),簡單說下,下面兩句都是創(chuàng)建一個(gè)空的數(shù)組:
var arr = []; var arr2 = new Array(); // 不寫new也可以。
在創(chuàng)建之后,你就可以隨時(shí)往數(shù)組里添加元素。數(shù)組的大小是不固定的,可以像a[0] = 1這樣隨意添加。
然后到重點(diǎn)了,關(guān)于往數(shù)組里添加元素這件事。首先,你要知道數(shù)組是一個(gè)對象,而對象是一個(gè)鍵值對的集合(類似于java里面的map,python里面的dict,c#里面的Dictionary),對象可以有屬性,對象的函數(shù)叫方法,對象的屬性或方法可以使用方括號或點(diǎn)號的方式訪問,其中使用方括號引用要加引號,點(diǎn)號的使用只有在屬性名稱是一個(gè)合法的變量名稱的時(shí)候才可以使用,也就是屬性不包含任何空格連字符并且不以數(shù)字開頭時(shí)才可以,看個(gè)例子:
var person = {}; person.age = 22; person.sayhi = function(){console.log('hi');}; person.age; // 22 person['age']; // 22 person.sayhi(); // hi person['sayhi'](); // hi
嗯,這就是對象,好像也沒什么特別的(除了用方括號取值外),不過對象說些就夠了,后面開始說數(shù)組。
對于上面的這些,數(shù)組全可以做到,也就是說,下面這段代碼也可以正常運(yùn)行(只有第一行跟上面的不一樣):
var person = []; person.age = 22; person.sayhi = function(){console.log('hi');}; person.age; // 22 person['age']; // 22 person.sayhi(); // hi person['sayhi'](); // hi
因?yàn)閿?shù)組就是對象,這里不要把方括號的字符串索引和通常講的數(shù)字索引弄混了,還沒開始說(馬上說)數(shù)字索引呢。
和普通的對象不同,數(shù)組對象的元素有數(shù)字索引,或者說特殊的鍵(前面說了對象是鍵值對),這和我們在其他語言比如java、c#等語言中的見到的數(shù)組是一樣的。在js中,這個(gè)鍵有一些特殊的要求,它可以是數(shù)字,也可以是能轉(zhuǎn)換成數(shù)字的字符串,而合理的數(shù)字,需要是范圍在0到4294967295(2^32-1)的整數(shù)(事實(shí)上,這個(gè)索引在詞法分析的時(shí)候都是當(dāng)做字符串的,js把這個(gè)字符串轉(zhuǎn)換成32位的整數(shù),然后再把32位的整數(shù)轉(zhuǎn)換成字符串跟原字符串比較,如果相同的話,則說明這個(gè)索引值是合法的數(shù)字,否則就是一個(gè)普通的字符串鍵)。簡單舉個(gè)例子:
a = [1, 3, 5, 7]; console.log(a[0]); // 1 console.log(a['0']); // 1 a['2'] = 12; console.log(a[2]); // 12
上面的代碼都是可以在瀏覽器里運(yùn)行的,注釋是輸出值。這和我們在其他語言中見到的數(shù)組好像沒啥區(qū)別。這個(gè)a['2'] = 12;因?yàn)?2'被轉(zhuǎn)換成整數(shù)再轉(zhuǎn)換成字符串還是'2',所以跟a[2]一樣。不過其他語言里,我們使用數(shù)組都是定義一個(gè)固定大小數(shù)組的對不對?這里好像不是哈,而且這里還說了數(shù)組的索引范圍。所以,為什么?簡單點(diǎn)回答就是這里的數(shù)組是對象,是js中的對象。這一點(diǎn)和其他語言(python等函數(shù)式的除外)不同,具體哪里不同,我沒深入研究,也說不太清楚,我理解的是,c/java等語言定義數(shù)組的時(shí)候,是在內(nèi)存中劃分了一塊固定大小的區(qū)域,有一個(gè)指針存儲著這塊區(qū)域的首地址。而js中好像不是這樣的,就像前面說的一樣,數(shù)組是對象,鍵值對結(jié)構(gòu),所以我覺得js中的數(shù)組都是用hash的方式存儲元素的,元素之間的內(nèi)存不一定是連續(xù)的。不過我現(xiàn)在沒找到查看js變量內(nèi)存地址的方法,所以沒法確定這件事。不過這不是本文要講的重點(diǎn)。
我們把重點(diǎn)放到索引上,前面說了索引的范圍,不過有同學(xué)可能試了,就是a[-1] = 2;或是a[4294967296] = 10;這種語句也沒有問題。對的,這并不是錯(cuò)誤,這是正常的語句,當(dāng)然不會有問題。但是問題是前面不是說了索引必須是0到4294967295的整數(shù)么?對,是的,這也沒錯(cuò)。那疑問出在哪里呢?
先貼兩張firefox控制臺的截圖:
你有沒有發(fā)現(xiàn)什么問題呢?當(dāng)我們使用正常的索引添加元素,在打印數(shù)組的時(shí)候,添加的元素會被打印出來,而使用非正常的“索引”添加元素時(shí),打印的數(shù)組里面卻沒有添加的元素,但是你看右側(cè)的Array對象,所有添加的元素卻一個(gè)不少。再看一張圖,這次多添加幾個(gè)元素,再給數(shù)組添加一個(gè)屬性(注意看右側(cè)Array對象的元素索引):
不知道你有沒有發(fā)現(xiàn)。在右側(cè),上面幾個(gè)是數(shù)字索引,打印數(shù)組的時(shí)候能被打印的,而下面幾個(gè)是屬性,打印數(shù)組不會打印屬性!也就是說,a[-2] = 2;這種語句,這個(gè)-2是屬性的鍵,而不是特殊的數(shù)字索引的鍵,-2在被強(qiáng)制轉(zhuǎn)換成正整數(shù)的時(shí)候,被認(rèn)為是一個(gè)字符串,所以這個(gè)-2和4294967296和'name'一樣,都是數(shù)組的一個(gè)屬性的鍵!所以前面說的負(fù)索引或是超出范圍的索引(應(yīng)該說是屬性的鍵)都是合法的,它們都是普通的字符串鍵。
這里一個(gè)問題,就是既然說-2這種鍵是普通的屬性鍵,那有人可能會說為什么使用a.-2或是a.'-2'訪問-2這個(gè)鍵的值會報(bào)錯(cuò),而a[-2]就不會報(bào)錯(cuò)?對呀,為什么?前面在講對象的時(shí)候,有一句加粗的話:對象的屬性或方法可以使用方括號或點(diǎn)號的方式訪問,其中使用方括號引用要加引號,點(diǎn)號的使用只有在屬性名稱是一個(gè)合法的變量名稱的時(shí)候才可以使用,也就是屬性不包含任何空格連字符并且不以數(shù)字開頭時(shí)才可以。所以,-2這種鍵的屬性,是不能用點(diǎn)號的方式訪問的!
另外還有一個(gè)小問題,就是方括號,當(dāng)我們想訪問數(shù)組的name屬性的時(shí)候,需要這樣:a['name'],也就是name被引號包起來了,而-2是和name一樣的屬性的鍵,為何-2可以不用(也可以用)引號包起來?其實(shí),方括號內(nèi)的所有字符會被當(dāng)成一個(gè)表達(dá)式,單純的一個(gè)數(shù)字-2,是個(gè)合法的表達(dá)式,但name如果沒有被定義成變量名,name就不是合法的表達(dá)式,同樣x^b&c這種也不是合法的,因?yàn)樗鼤划?dāng)成變量x、b、c組成的某種表達(dá)式,但是x、b、c是不是變量還不確定,而且里面的符號不一定是被js所支持的,所以a[name]的問題出在name上,而不是[]上。如果還不好理解,你可以把name想象成x+y,在x、y沒有被定義成變量的時(shí)候,x+y這個(gè)表達(dá)式肯定有問題對不對?那a[x+y]也會有問題對不對?而a['x+y']就沒有問題,因?yàn)?x+y'是個(gè)字符串。
后面補(bǔ)充一點(diǎn),js中,變量名字是可以由數(shù)字、字母、下劃線任意組合的,其中數(shù)字不能放在開始位置。而對象的屬性鍵的命名要寬松一些,合法的可以不用引號,不合法的用引號包起來就可以。
好了,說的差不多了,總結(jié)一下:文章首先簡單介紹了下對象,然后說了數(shù)組也是對象,最后解釋了下一些疑問,然后總結(jié)。
寫這篇文章的原因是我昨天在微博里看了一條js的教程,對數(shù)組的講解產(chǎn)生了一個(gè)疑問,然后評論的字?jǐn)?shù)超出了140,所以我就查資料單獨(dú)寫出來了。目的是讓自己弄明白,也愿能幫助到學(xué)js的同學(xué)。數(shù)組范圍和索引轉(zhuǎn)換那里是參考的《Speaking Javascript》,其他地方都是自己的理解和看法。
最后,感謝觀看,因?yàn)槭欠謨纱螌懙?,可能語句有些亂,有的地方不亂但是上下文也完整,有的上下文完整但是廢話太多,總之,就這樣吧。下篇見。
- 在JS數(shù)組特定索引處指定位置插入元素的技巧
- JS數(shù)組操作(數(shù)組增加、刪除、翻轉(zhuǎn)、轉(zhuǎn)字符串、取索引、截取(切片)slice、剪接splice、數(shù)組合并)
- javascript檢查某個(gè)元素在數(shù)組中的索引值
- JavaScript通過元素索引號刪除數(shù)組中對應(yīng)元素的方法
- 利用js查找數(shù)組中指定元素并返回該元素的所有索引示例
- 在JS數(shù)組特定索引處指定位置插入元素
- js以對象為索引的關(guān)聯(lián)數(shù)組
- JavaScript中的索引數(shù)組、關(guān)聯(lián)數(shù)組和靜態(tài)數(shù)組、動(dòng)態(tài)數(shù)組講解
- JS算法題之查找數(shù)字在數(shù)組中的索引位置
- JS數(shù)組索引檢測中的數(shù)據(jù)類型問題詳解
相關(guān)文章
layui table checked獲取選中數(shù)據(jù)方式
這篇文章主要介紹了layui table checked獲取選中數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10Javascript實(shí)現(xiàn)可旋轉(zhuǎn)的圓圈實(shí)例代碼
這篇文章主要介紹了Javascript實(shí)現(xiàn)可旋轉(zhuǎn)的圓圈實(shí)例代碼,可實(shí)現(xiàn)圓圈的旋轉(zhuǎn)與運(yùn)動(dòng)效果,涉及javascript動(dòng)態(tài)操作頁面元素屬性及進(jìn)行相應(yīng)數(shù)學(xué)運(yùn)算的技巧,需要的朋友可以參考下2015-08-08JS清除字符串中重復(fù)值的實(shí)現(xiàn)方法
這篇文章主要介紹了JS清除字符串中重復(fù)值的實(shí)現(xiàn)方法,涉及javascript數(shù)組與字符串的遍歷、比較及數(shù)學(xué)運(yùn)算相關(guān)技巧,需要的朋友可以參考下2016-08-08部分網(wǎng)站允許空白referer的防盜鏈圖片的js破解代碼
主要是有些網(wǎng)站的圖片調(diào)用是防盜鏈的但一般只是判斷referer是不是自己網(wǎng)站,如果referer為空也會顯示圖片,所以有了下面的代碼。2011-05-05基于 antd pro 的短信驗(yàn)證碼登錄功能(流程分析)
這篇文章主要介紹了基于 antd pro 的短信驗(yàn)證碼登錄功能(流程分析),本文通過實(shí)例代碼流程分析給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05