案例分析
var obj = {
count: 1
}
var myArray = ['red', 'white', 'black'];
console.log(myArray.length);
myArray.obj = obj;
console.log(myArray.length);
兩次打印myArray的length是多少?為什么?
理想與現實的沖突
我認為結果應該是 3 4
但結果是 4 4
打印的數組如我所想 [ 'red', 'white', 'black', obj: { count: 1 } ]
然length 仍然為3
老實說,一上來就被整懵逼了。
從現實出發
可仔細一看,案例本來就沒有給數組多增加元素個數。
myArray.obj = obj;
這一點非常關鍵 案例用的時 點語法 賦值操作,那么意思就是給myarray數組增加了一個obj屬性。屬性值是定義的obj對象。
而真正的向數組添加元素 用的是數組的 push方法。push才是真正的向數組中添加一個元素。
如果代碼改成這樣,數組長度就是理想的長度了。
myArray.push(obj);
console.log(myArray);
console.log(myArray.length);
而.obj只是為當前的這個數組增加屬性,
myArray.name = 'xiaoming';
console.log(myArray);
console.log(myArray.length);
實驗表明,使用.屬性只能增加數組的屬性,
而這些屬性和值通常通過鍵值對的形式放在數組元素的后面,而不會增加數組的個數。
[ 'red', 'white', 'black', obj: { count: 1 } ]
對數組長度的理解
數組長度:
The length property of an object which is an instance of type Array sets or returns the number of elements in that array. The value is an unsigned, 32-bit integer that is always numerically reater than the highest index in the array.
- length 屬性 是數組設置或返回數組中的元素個數。它的值是無符號32位整數,始終數值上大于數組中的最高索引。
var fruits = [];
fruits.push('banana', 'apple', 'peach');
console.log(fruits.length); // 3
// 當給數組設置一個屬性,當這個屬性是合法的數組索引,并且數組索引超出了當前數組的邊界,引擎就會相應的更新數組的length屬性
fruits[5] = 'mango';
console.log(fruits[5]); // 'mango'
console.log(Object.keys(fruits)); // ['0', '1', '2', '5']
console.log(fruits.length); // 6
- 由于length可以取值也可以賦值,所以length屬性并不能確切的表示數組中元素的個數,解釋如下:
You can set the length property to truncate an array at any time. When you extend an array by changing its length property, the number of actual elements does not increase; for example, if you set length to 3 when it is currently 2, the array still contains only 2 elements. Thus, the length property does not necessarily indicate the number of defined values in the array. See also Relationship between length and numerical properties.
你可以隨時設置length屬性來縮短一個數組,它真的就縮小的,只會保留length個元素。
當你通過改變length屬性擴大數組時,實際的元素個數并沒有增加,例如,當前數組有2個元素,把length設置為3,數組依然只包含2個元素。因此 length屬性不能確切的反映數組中的元素個數。
length和數字屬性的關系
我們知道數組是通過索引訪問的 或者說 通過下標來訪問的。那么下標其實就是數字屬性,而數組的length屬性是和數字屬性連在一起的。
其中數組幾個內置的函數(比如, join, slice, indexOf, 等) 被調用時會計算數組的length屬性,
其他的方法(比如, push, splice, 等)也會更新數組的length屬性既然屬性可以用點語法訪問,為什么數字屬性不行
屬性一般可以通過點語法訪問,這要求點語法點到的必須是一個合法命名的變量。而合法的命名是不允許以數字開頭的。
所以這個屬性只能通過括號表示法方法 即myArray[0]
- 關于數組中有多少個元素的思考
通過上述分析,我們知道length屬性并不能正確表示數組中有多少個元素。
比如說修改數組的最高索引,或者更直接點直接修改length屬性的值,這樣都無法反應數組到底有幾個元素。
這就有個問題,如何知道數組中到底有多少個元素?
上面打印結果的 obj:{count:1}是不是數組的元素呢?應不應該算上?
數組的屬性是數字,通過索引訪問。數組的索引就是數組特殊的屬性名,而obj不是數字屬性 以這種形式展示在數組中 obj:{count:1} 那么數組本質上或許也是這么寫的[0:'red',1:'white']
那么我個人覺得要算上,數組中鍵的個數就代表了數組中有多少個元素
console.log(Object.keys(myArray).length);
然而這么算就會有一個困惑。還好這個屬性是添加在具體的數組中的,所以才有顯示出來,如果是在Array.prototype中定義的,那么就不會打印出來。所以我覺得非數字類索引是不需要的算入有多少個元素的。
如果要算有多少個元素,就要排除到這些非數字屬性。
總結與應用
如果看到鍵值對的形式(外面沒有括號包裹,即非獨立對象)出現在數組中,
那它就不是作為數組元素存在的,而是作為數組的屬性或方法存在的。
這就意味著 可以給數組增加 屬性和方法 方便我們使用了。
比如返回每個數組的平方
var myArray = [1,2,3,4,5];
myArray.square = function () {
for (var i = this.length - 1; i >= 0; i--) {
this[i] *= this[i];
}
return this;
};
console.log(myArray.square());
加深理解
我查了查,這個東西其實叫做原型prototype其作用就是給對象添加屬性和方法的。上述鏈接是W3C的參考例子。是從具體的對象層面增加的屬性和方法。案例也是這個意思。
還可以給每一個對象增加屬性和方法,這是MDN對Array.prototype的解釋,比如給Array增加一個first方法,那么所有的數組實例都擁有這個方法,而且打印數組時,此方法在數組中不會看到。
console.log(myArray.square());
if (!Array.prototype.first) {
Array.prototype.first = function() {
return this[0];
}
}
console.log(myArray.first());