從題目提及,之因此是不徹底,是由於有些東西好比數組的方法怎麼用這個我都不打算講,由於那個看一下都會,下面講的都是我以爲重要的,只關於數組對象自己。另外,因爲個人Javascript實戰經驗很少,因此可能有些東西沒涉及到,有些內容說的有誤,請發現問題的同窗不吝指教。java
首先,Javascript(下稱js)的數組定義,這不是重點,簡單說下,下面兩句都是建立一個空的數組:python
var arr = []; var arr2 = new Array(); // 不寫new也能夠。
在建立以後,你就能夠隨時往數組裏添加元素。數組的大小是不固定的,能夠像a[0] = 1
這樣隨意添加。c#
而後到重點了,關於往數組裏添加元素這件事。首先,你要知道數組是一個對象,而對象是一個鍵值對的集合(相似於java裏面的map,python裏面的dict,c#裏面的Dictionary),對象能夠有屬性,對象的函數叫方法,對象的屬性或方法可使用方括號或點號的方式訪問,其中使用方括號引用要加引號,點號的使用只有在屬性名稱是一個合法的變量名稱的時候纔可使用,也就是屬性不包含任何空格連字符而且不以數字開頭時才能夠,看個例子:數組
var person = {}; person.age = 22; person.sayhi = function(){console.log('hi');}; person.age; // 22 person['age']; // 22 person.sayhi(); // hi person['sayhi'](); // hi
嗯,這就是對象,好像也沒什麼特別的(除了用方括號取值外),不過對象說些就夠了,後面開始說數組。瀏覽器
對於上面的這些,數組全能夠作到,也就是說,下面這段代碼也能夠正常運行(只有第一行跟上面的不同):函數
var person = []; person.age = 22; person.sayhi = function(){console.log('hi');}; person.age; // 22 person['age']; // 22 person.sayhi(); // hi person['sayhi'](); // hi
由於數組就是對象,這裏不要把方括號的字符串索引和一般講的數字索引弄混了,還沒開始說(立刻說)數字索引呢。spa
和普通的對象不一樣,數組對象的元素有數字索引,或者說特殊的鍵(前面說了對象是鍵值對),這和咱們在其餘語言好比java、c#等語言中的見到的數組是同樣的。在js中,這個鍵有一些特殊的要求,它能夠是數字,也能夠是能轉換成數字的字符串,而合理的數字,須要是範圍在0到4294967295(2^32-1)的整數(事實上,這個索引在詞法分析的時候都是當作字符串的,js把這個字符串轉換成32位的整數,而後再把32位的整數轉換成字符串跟原字符串比較,若是相同的話,則說明這個索引值是合法的數字,不然就是一個普通的字符串鍵)。簡單舉個例子:firefox
a = [1, 3, 5, 7]; console.log(a[0]); // 1 console.log(a['0']); // 1 a['2'] = 12; console.log(a[2]); // 12
上面的代碼都是能夠在瀏覽器裏運行的,註釋是輸出值。這和咱們在其餘語言中見到的數組好像沒啥區別。這個a['2'] = 12;
由於'2'
被轉換成整數再轉換成字符串仍是'2'
,因此跟a[2]
同樣。不過其餘語言裏,咱們使用數組都是定義一個固定大小數組的對不對?這裏好像不是哈,並且這裏還說了數組的索引範圍。因此,爲何?簡單點回答就是這裏的數組是對象,是js中的對象。這一點和其餘語言(python等函數式的除外)不一樣,具體哪裏不一樣,我沒深刻研究,也說不太清楚,我理解的是,c/java等語言定義數組的時候,是在內存中劃分了一塊固定大小的區域,有一個指針存儲着這塊區域的首地址。而js中好像不是這樣的,就像前面說的同樣,數組是對象,鍵值對結構,因此我以爲js中的數組都是用hash的方式存儲元素的,元素之間的內存不必定是連續的。不過我如今沒找到查看js變量內存地址的方法,因此無法肯定這件事。不過這不是本文要講的重點。指針
咱們把重點放到索引上,前面說了索引的範圍,不過有同窗可能試了,就是a[-1] = 2;
或是a[4294967296] = 10;
這種語句也沒有問題。對的,這並非錯誤,這是正常的語句,固然不會有問題。可是問題是前面不是說了索引必須是0到4294967295的整數麼?對,是的,這也沒錯。那疑問出在哪裏呢?code
先貼兩張firefox控制檯的截圖:
你有沒有發現什麼問題呢?當咱們使用正常的索引添加元素,在打印數組的時候,添加的元素會被打印出來,而使用非正常的「索引」添加元素時,打印的數組裏面卻沒有添加的元素,可是你看右側的Array對象,全部添加的元素卻一個很多。再看一張圖,此次多添加幾個元素,再給數組添加一個屬性(注意看右側Array對象的元素索引):
不知道你有沒有發現。在右側,上面幾個是數字索引,打印數組的時候能被打印的,而下面幾個是屬性,打印數組不會打印屬性!也就是說,a[-2] = 2;
這種語句,這個-2是屬性的鍵,而不是特殊的數字索引的鍵,-2在被強制轉換成正整數的時候,被認爲是一個字符串,因此這個-2和4294967296和'name'同樣,都是數組的一個屬性的鍵!因此前面說的負索引或是超出範圍的索引(應該說是屬性的鍵)都是合法的,它們都是普通的字符串鍵。
這裏一個問題,就是既然說-2這種鍵是普通的屬性鍵,那有人可能會說爲何使用a.-2
或是a.'-2'
訪問-2這個鍵的值會報錯,而a[-2]就不會報錯?對呀,爲何?前面在講對象的時候,有一句加粗的話:對象的屬性或方法可使用方括號或點號的方式訪問,其中使用方括號引用要加引號,點號的使用只有在屬性名稱是一個合法的變量名稱的時候纔可使用,也就是屬性不包含任何空格連字符而且不以數字開頭時才能夠。因此,-2這種鍵的屬性,是不能用點號的方式訪問的!
另外還有一個小問題,就是方括號,當咱們想訪問數組的name屬性的時候,須要這樣:a['name']
,也就是name被引號包起來了,而-2是和name同樣的屬性的鍵,爲什麼-2能夠不用(也能夠用)引號包起來?其實,方括號內的全部字符會被當成一個表達式,單純的一個數字-2,是個合法的表達式,但name若是沒有被定義成變量名,name就不是合法的表達式,一樣x^b&c這種也不是合法的,由於它會被當成變量x、b、c組成的某種表達式,可是x、b、c是否是變量還不肯定,並且裏面的符號不必定是被js所支持的,因此a[name]
的問題出在name上,而不是[]上。若是還很差理解,你能夠把name想象成x+y,在x、y沒有被定義成變量的時候,x+y
這個表達式確定有問題對不對?那a[x+y]
也會有問題對不對?而a['x+y']
就沒有問題,由於'x+y'
是個字符串。
後面補充一點,js中,變量名字是能夠由數字、字母、下劃線任意組合的,其中數字不能放在開始位置。而對象的屬性鍵的命名要寬鬆一些,合法的能夠不用引號,不合法的用引號包起來就能夠。
好了,說的差很少了,總結一下:文章首先簡單介紹了下對象,而後說了數組也是對象,最後解釋了下一些疑問,而後總結。
寫這篇文章的緣由是我昨天在微博裏看了一條js的教程,對數組的講解產生了一個疑問,而後評論的字數超出了140,因此我就查資料單獨寫出來了。目的是讓本身弄明白,也願能幫助到學js的同窗。數組範圍和索引轉換那裏是參考的《Speaking Javascript》,其餘地方都是本身的理解和見解。
最後,感謝觀看,由於是分兩次寫的,可能語句有些亂,有的地方不亂可是上下文也完整,有的上下文完整可是廢話太多,總之,就這樣吧。下篇見。