<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 數組 ## 定義 數組(array)是按次序排列的一組值。每個值的位置都有編號(從0開始),整個數組用方括號表示。 ```javascript var arr = ['a', 'b', 'c']; ``` 上面代碼中的`a`、`b`、`c`就構成一個數組,兩端的方括號是數組的標志。`a`是0號位置,`b`是1號位置,`c`是2號位置。 除了在定義時賦值,數組也可以先定義后賦值。 ```javascript var arr = []; arr[0] = 'a'; arr[1] = 'b'; arr[2] = 'c'; ``` 任何類型的數據,都可以放入數組。 ```javascript var arr = [ {a: 1}, [1, 2, 3], function() {return true;} ]; arr[0] // Object {a: 1} arr[1] // [1, 2, 3] arr[2] // function (){return true;} ``` 上面數組`arr`的3個成員依次是對象、數組、函數。 如果數組的元素還是數組,就形成了多維數組。 ```javascript var a = [[1, 2], [3, 4]]; a[0][1] // 2 a[1][1] // 4 ``` ## 數組的本質 本質上,數組屬于一種特殊的對象。`typeof`運算符會返回數組的類型是`object`。 ```javascript typeof [1, 2, 3] // "object" ``` 上面代碼表明,`typeof`運算符認為數組的類型就是對象。 數組的特殊性體現在,它的鍵名是按次序排列的一組整數(0,1,2...)。 ```javascript var arr = ['a', 'b', 'c']; Object.keys(arr) // ["0", "1", "2"] ``` 上面代碼中,`Object.keys`方法返回數組的所有鍵名。可以看到數組的鍵名就是整數0、1、2。 由于數組成員的鍵名是固定的(默認總是0、1、2...),因此數組不用為每個元素指定鍵名,而對象的每個成員都必須指定鍵名。JavaScript 語言規定,對象的鍵名一律為字符串,所以,數組的鍵名其實也是字符串。之所以可以用數值讀取,是因為非字符串的鍵名會被轉為字符串。 ```javascript var arr = ['a', 'b', 'c']; arr['0'] // 'a' arr[0] // 'a' ``` 上面代碼分別用數值和字符串作為鍵名,結果都能讀取數組。原因是數值鍵名被自動轉為了字符串。 注意,這點在賦值時也成立。一個值總是先轉成字符串,再作為鍵名進行賦值。 ```javascript var a = []; a[1.00] = 6; a[1] // 6 ``` 上面代碼中,由于`1.00`轉成字符串是`1`,所以通過數字鍵`1`可以讀取值。 上一章說過,對象有兩種讀取成員的方法:點結構(`object.key`)和方括號結構(`object[key]`)。但是,對于數值的鍵名,不能使用點結構。 ```javascript var arr = [1, 2, 3]; arr.0 // SyntaxError ``` 上面代碼中,`arr.0`的寫法不合法,因為單獨的數值不能作為標識符(identifier)。所以,數組成員只能用方括號`arr[0]`表示(方括號是運算符,可以接受數值)。 ## length 屬性 數組的`length`屬性,返回數組的成員數量。 ```javascript ['a', 'b', 'c'].length // 3 ``` JavaScript 使用一個32位整數,保存數組的元素個數。這意味著,數組成員最多只有 4294967295 個(2<sup>32</sup> - 1)個,也就是說`length`屬性的最大值就是 4294967295。 只要是數組,就一定有`length`屬性。該屬性是一個動態的值,等于鍵名中的最大整數加上`1`。 ```javascript var arr = ['a', 'b']; arr.length // 2 arr[2] = 'c'; arr.length // 3 arr[9] = 'd'; arr.length // 10 arr[1000] = 'e'; arr.length // 1001 ``` 上面代碼表示,數組的數字鍵不需要連續,`length`屬性的值總是比最大的那個整數鍵大`1`。另外,這也表明數組是一種動態的數據結構,可以隨時增減數組的成員。 `length`屬性是可寫的。如果人為設置一個小于當前成員個數的值,該數組的成員數量會自動減少到`length`設置的值。 ```javascript var arr = [ 'a', 'b', 'c' ]; arr.length // 3 arr.length = 2; arr // ["a", "b"] ``` 上面代碼表示,當數組的`length`屬性設為2(即最大的整數鍵只能是1)那么整數鍵2(值為`c`)就已經不在數組中了,被自動刪除了。 清空數組的一個有效方法,就是將`length`屬性設為0。 ```javascript var arr = [ 'a', 'b', 'c' ]; arr.length = 0; arr // [] ``` 如果人為設置`length`大于當前元素個數,則數組的成員數量會增加到這個值,新增的位置都是空位。 ```javascript var a = ['a']; a.length = 3; a[1] // undefined ``` 上面代碼表示,當`length`屬性設為大于數組個數時,讀取新增的位置都會返回`undefined`。 如果人為設置`length`為不合法的值,JavaScript 會報錯。 ```javascript // 設置負值 [].length = -1 // RangeError: Invalid array length // 數組元素個數大于等于2的32次方 [].length = Math.pow(2, 32) // RangeError: Invalid array length // 設置字符串 [].length = 'abc' // RangeError: Invalid array length ``` 值得注意的是,由于數組本質上是一種對象,所以可以為數組添加屬性,但是這不影響`length`屬性的值。 ```javascript var a = []; a['p'] = 'abc'; a.length // 0 a[2.1] = 'abc'; a.length // 0 ``` 上面代碼將數組的鍵分別設為字符串和小數,結果都不影響`length`屬性。因為,`length`屬性的值就是等于最大的數字鍵加1,而這個數組沒有整數鍵,所以`length`屬性保持為`0`。 如果數組的鍵名是添加超出范圍的數值,該鍵名會自動轉為字符串。 ```javascript var arr = []; arr[-1] = 'a'; arr[Math.pow(2, 32)] = 'b'; arr.length // 0 arr[-1] // "a" arr[4294967296] // "b" ``` 上面代碼中,我們為數組`arr`添加了兩個不合法的數字鍵,結果`length`屬性沒有發生變化。這些數字鍵都變成了字符串鍵名。最后兩行之所以會取到值,是因為取鍵值時,數字鍵名會默認轉為字符串。 ## in 運算符 檢查某個鍵名是否存在的運算符`in`,適用于對象,也適用于數組。 ```javascript var arr = [ 'a', 'b', 'c' ]; 2 in arr // true '2' in arr // true 4 in arr // false ``` 上面代碼表明,數組存在鍵名為`2`的鍵。由于鍵名都是字符串,所以數值`2`會自動轉成字符串。 注意,如果數組的某個位置是空位,`in`運算符返回`false`。 ```javascript var arr = []; arr[100] = 'a'; 100 in arr // true 1 in arr // false ``` 上面代碼中,數組`arr`只有一個成員`arr[100]`,其他位置的鍵名都會返回`false`。 ## for...in 循環和數組的遍歷 `for...in`循環不僅可以遍歷對象,也可以遍歷數組,畢竟數組只是一種特殊對象。 ```javascript var a = [1, 2, 3]; for (var i in a) { console.log(a[i]); } // 1 // 2 // 3 ``` 但是,`for...in`不僅會遍歷數組所有的數字鍵,還會遍歷非數字鍵。 ```javascript var a = [1, 2, 3]; a.foo = true; for (var key in a) { console.log(key); } // 0 // 1 // 2 // foo ``` 上面代碼在遍歷數組時,也遍歷到了非整數鍵`foo`。所以,不推薦使用`for...in`遍歷數組。 數組的遍歷可以考慮使用`for`循環或`while`循環。 ```javascript var a = [1, 2, 3]; // for循環 for(var i = 0; i < a.length; i++) { console.log(a[i]); } // while循環 var i = 0; while (i < a.length) { console.log(a[i]); i++; } var l = a.length; while (l--) { console.log(a[l]); } ``` 上面代碼是三種遍歷數組的寫法。最后一種寫法是逆向遍歷,即從最后一個元素向第一個元素遍歷。 數組的`forEach`方法,也可以用來遍歷數組,詳見《標準庫》的 Array 對象一章。 ```javascript var colors = ['red', 'green', 'blue']; colors.forEach(function (color) { console.log(color); }); // red // green // blue ``` ## 數組的空位 當數組的某個位置是空元素,即兩個逗號之間沒有任何值,我們稱該數組存在空位(hole)。 ```javascript var a = [1, , 1]; a.length // 3 ``` 上面代碼表明,數組的空位不影響`length`屬性。 需要注意的是,如果最后一個元素后面有逗號,并不會產生空位。也就是說,有沒有這個逗號,結果都是一樣的。 ```javascript var a = [1, 2, 3,]; a.length // 3 a // [1, 2, 3] ``` 上面代碼中,數組最后一個成員后面有一個逗號,這不影響`length`屬性的值,與沒有這個逗號時效果一樣。 數組的空位是可以讀取的,返回`undefined`。 ```javascript var a = [, , ,]; a[1] // undefined ``` 使用`delete`命令刪除一個數組成員,會形成空位,并且不會影響`length`屬性。 ```javascript var a = [1, 2, 3]; delete a[1]; a[1] // undefined a.length // 3 ``` 上面代碼用`delete`命令刪除了數組的第二個元素,這個位置就形成了空位,但是對`length`屬性沒有影響。也就是說,`length`屬性不過濾空位。所以,使用`length`屬性進行數組遍歷,一定要非常小心。 數組的某個位置是空位,與某個位置是`undefined`,是不一樣的。如果是空位,使用數組的`forEach`方法、`for...in`結構、以及`Object.keys`方法進行遍歷,空位都會被跳過。 ```javascript var a = [, , ,]; a.forEach(function (x, i) { console.log(i + '. ' + x); }) // 不產生任何輸出 for (var i in a) { console.log(i); } // 不產生任何輸出 Object.keys(a) // [] ``` 如果某個位置是`undefined`,遍歷的時候就不會被跳過。 ```javascript var a = [undefined, undefined, undefined]; a.forEach(function (x, i) { console.log(i + '. ' + x); }); // 0. undefined // 1. undefined // 2. undefined for (var i in a) { console.log(i); } // 0 // 1 // 2 Object.keys(a) // ['0', '1', '2'] ``` 這就是說,空位就是數組沒有這個元素,所以不會被遍歷到,而`undefined`則表示數組有這個元素,值是`undefined`,所以遍歷不會跳過。 ## 類似數組的對象 如果一個對象的所有鍵名都是正整數或零,并且有`length`屬性,那么這個對象就很像數組,語法上稱為“類似數組的對象”(array-like object)。 ```javascript var obj = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; obj[0] // 'a' obj[1] // 'b' obj.length // 3 obj.push('d') // TypeError: obj.push is not a function ``` 上面代碼中,對象`obj`就是一個類似數組的對象。但是,“類似數組的對象”并不是數組,因為它們不具備數組特有的方法。對象`obj`沒有數組的`push`方法,使用該方法就會報錯。 “類似數組的對象”的根本特征,就是具有`length`屬性。只要有`length`屬性,就可以認為這個對象類似于數組。但是有一個問題,這種`length`屬性不是動態值,不會隨著成員的變化而變化。 ```javascript var obj = { length: 0 }; obj[3] = 'd'; obj.length // 0 ``` 上面代碼為對象`obj`添加了一個數字鍵,但是`length`屬性沒變。這就說明了`obj`不是數組。 典型的“類似數組的對象”是函數的`arguments`對象,以及大多數 DOM 元素集,還有字符串。 ```javascript // arguments對象 function args() { return arguments } var arrayLike = args('a', 'b'); arrayLike[0] // 'a' arrayLike.length // 2 arrayLike instanceof Array // false // DOM元素集 var elts = document.getElementsByTagName('h3'); elts.length // 3 elts instanceof Array // false // 字符串 'abc'[1] // 'b' 'abc'.length // 3 'abc' instanceof Array // false ``` 上面代碼包含三個例子,它們都不是數組(`instanceof`運算符返回`false`),但是看上去都非常像數組。 數組的`slice`方法可以將“類似數組的對象”變成真正的數組。 ```javascript var arr = Array.prototype.slice.call(arrayLike); ``` 除了轉為真正的數組,“類似數組的對象”還有一個辦法可以使用數組的方法,就是通過`call()`把數組的方法放到對象上面。 ```javascript function print(value, index) { console.log(index + ' : ' + value); } Array.prototype.forEach.call(arrayLike, print); ``` 上面代碼中,`arrayLike`代表一個類似數組的對象,本來是不可以使用數組的`forEach()`方法的,但是通過`call()`,可以把`forEach()`嫁接到`arrayLike`上面調用。 下面的例子就是通過這種方法,在`arguments`對象上面調用`forEach`方法。 ```javascript // forEach 方法 function logArgs() { Array.prototype.forEach.call(arguments, function (elem, i) { console.log(i + '. ' + elem); }); } // 等同于 for 循環 function logArgs() { for (var i = 0; i < arguments.length; i++) { console.log(i + '. ' + arguments[i]); } } ``` 字符串也是類似數組的對象,所以也可以用`Array.prototype.forEach.call`遍歷。 ```javascript Array.prototype.forEach.call('abc', function (chr) { console.log(chr); }); // a // b // c ``` 注意,這種方法比直接使用數組原生的`forEach`要慢,所以最好還是先將“類似數組的對象”轉為真正的數組,然后再直接調用數組的`forEach`方法。 ```javascript var arr = Array.prototype.slice.call('abc'); arr.forEach(function (chr) { console.log(chr); }); // a // b // c ``` ## 參考鏈接 - Axel Rauschmayer, [Arrays in JavaScript](http://www.2ality.com/2012/12/arrays.html) - Axel Rauschmayer, [JavaScript: sparse arrays vs. dense arrays](http://www.2ality.com/2012/06/dense-arrays.html) - Felix Bohm, [What They Didn’t Tell You About ES5′s Array Extras](http://net.tutsplus.com/tutorials/javascript-ajax/what-they-didnt-tell-you-about-es5s-array-extras/) - Juriy Zaytsev, [How ECMAScript 5 still does not allow to subclass an array](http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看