在JavaScript中,除了5種原始數據類型以外,其餘全部的都是對象,包括函數(Function)。javascript
基本數據類型:String,boolean,Number,Undefined, Nullphp
引用數據類型:Object(Array,Date,RegExp,Function)java
在這個前提下,我們再來討論JavaScript的對象。node
var obj = {}; //種方式建立對象,被稱之爲對象直接量(Object Literal) var obj = new Object(); // 建立一個空對象,和{}同樣
更多建立對象的知識,參見《JavaScript權威指南(第6版)》第6章算法
二、建立數組數組
var arr = [];//這是使用數組直接量(Array Literal)建立數組 var arr = new Array();//構造函數Array() 建立數組對象
更多建立數組的知識,參見《JavaScript權威指南(第6版)》第7章。ide
在說區別以前,須要先提到另一個知識,就是JavaScript的原型繼承。全部JavaScript的內置構造函數都是繼承自 Object.prototype。在這個前提下,能夠理解爲使用 new Array() 或 [] 建立出來的數組對象,都會擁有 Object.prototype 的屬性值。函數
對於題主的問題意味着:測試
var obj = {};// 擁有Object.prototype的屬性值 var arr = []; //使用數組直接量建立的數組,因爲Array.prototype的屬性繼承自 Object.prototype, //那麼,它將同時擁有Array.prototype和Object.prototype的屬性值
能夠獲得對象和數組的第一個區別:對象沒有數組Array.prototype的屬性值spa
數組具備一個最基本特徵:索引,這是對象所沒有的,下面來看一段代碼:
var obj = {}; var arr = []; obj[2] = 'a'; arr[2] = 'a'; console.log(obj[2]); // 輸出 a console.log(arr[2]); // 輸出 a console.log(obj.length); // 輸出 undefined console.log(arr.length); // 輸出 3
經過上面這個測試,能夠看到,雖然 obj[2]與arr[2] 都輸出'a',可是,在輸出length上有明顯的差別,這是爲何呢?
obj[2]與arr[2]的區別
obj[2]輸出'a',是由於對象就是普通的鍵值對存取數據
而arr[2]輸出'a' 則不一樣,數組是經過索引來存取數據,arr[2]之因此輸出'a',是由於數組arr索引2的位置已經存儲了數據
obj.length與arr.length的區別
obj.length並不具備數組的特性,而且obj沒有保存屬性length,那麼天然就會輸出undefined
而對於數組來講,length是數組的一個內置屬性,數組會根據索引長度來更改length的值。
爲何arr.length輸出3,而不是1呢?
這是因爲數組的特殊實現機制,對於普通的數組,若是它的索引是從0開始連續的,那麼length的值就會等於數組中元素個數
而對於上面例子中arr,在給數組添加元素時,並無按照連續的索引添加,因此致使數組的索引不連續,那麼就致使索引長度大於元素個數,那麼咱們稱之爲稀疏數組。
有關稀疏數組的特性就再也不討論更多,參見《JavaScript權威指南(第6版)》7.3節。
定義:
一、擁有length屬性,其它屬性(索引)爲非負整數(對象中的索引會被當作字符串來處理,這裏你能夠當作是個非負整數串來理解)
二、不具備數組所具備的方法
僞數組,就是像數組同樣有 length
屬性,也有 0
、1
、2
、3
等屬性的對象,看起來就像數組同樣,但不是數組,好比
var fakeArray = { length: 3, "0": "first", "1": "second", "2": "third" }; for (var i = 0; i < fakeArray.length; i++) { console.log(fakeArray[i]); } Array.prototype.join.call(fakeArray,'+');
常見的參數的參數 arguments,DOM 對象列表(好比經過 document.getElementsByTags 獲得的列表),jQuery 對象(好比 $("div"))。
僞數組是一個 Object,而真實的數組是一個 Array
fakeArray instanceof Array === false; Object.prototype.toString.call(fakeArray) === "[object Object]"; var arr = [1,2,3,4,6]; arr instanceof Array === true; Object.prototype.toString.call(arr) === "[object Array]"
《javascript權威指南》上給出了代碼用來判斷一個對象是否屬於「類數組」。以下:
// Determine if o is an array-like object. // Strings and functions have numeric length properties, but are // excluded by the typeof test. In client-side JavaScript, DOM text // nodes have a numeric length property, and may need to be excluded // with an additional o.nodeType != 3 test. function isArrayLike(o) { if (o && // o is not null, undefined, etc. typeof o === 'object' && // o is an object isFinite(o.length) && // o.length is a finite number o.length >= 0 && // o.length is non-negative o.length===Math.floor(o.length) && // o.length is an integer o.length < 4294967296) // o.length < 2^32 return true; // Then o is array-like else return false; // Otherwise it is not }
不過有個更簡單的辦法來判斷,用 Array.isArray
Array.isArray(fakeArray) === false; Array.isArray(arr) === true;
從外觀上看僞數組,看不出來它與數組的區別,在JavaScript內置對象中常見的僞數組就是大名鼎鼎的auguments:
(function() { console.log(typeof arguments); // 輸出 object,它並非一個數組 }());
另外在DOM對象中,childNodes也是僞數組
console.log(typeof document.body.childNodes); // 輸出 object
除此以外,還有不少經常使用的僞數組,就不一一列舉。
僞數組存在的意義,是可讓普通的對象也能正常使用數組的不少算法,好比:
var arr = Array.prototype.slice.call(arguments) 或者 var arr = Array.prototype.slice.call(arguments, 0); // 將arguments對象轉換成一個真正的數組 Array.prototype.forEach.call(arguments, function(v) { // 循環arguments對象 });
除了使用 Array.prototype.slice.call(arguments),你也能夠簡單的使用[].slice.call(arguments) 來代替。另外,你可使用 bind 來簡化該過程。
var unboundSlice = Array.prototype.slice; var slice = Function.prototype.call.bind(unboundSlice); function list() { return slice(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3]
將具備length屬性的對象轉換成數組對象,arguments是每一個函數在運行的時候自動得到的一個近似數組的對象(傳入函數的參數從0開始按數字排列,並且有length)。
好比當你 func('a', 'b', 'c') 的時候,func裏面得到的arguments[0] 是 'a',arguments[1] 是 'b',依次類推。但問題在於這個arguments對象其實並非Array,因此沒有slice方法。Array.prototype.slice.call( )能夠間接對其實現slice的效果,並且返回的結果是真正的Array。
對於IE9之前的版本(DOM實現基於COM),咱們可使用makeArray來實現。
// 僞數組轉化成數組 var makeArray = function(obj) { if (!obj || obj.length === 0) { return []; } // 非僞類對象,直接返回最好 if (!obj.length) { return obj; } // 針對IE8之前 DOM的COM實現 try { return [].slice.call(obj); } catch (e) { var i = 0, j = obj.length, res = []; for (; i < j; i++) { res.push(obj[i]); } return res; } };
更多關於僞數組的知識,參見《JavaScript權威指南(第6版)》7.11節。
對象沒有數組Array.prototype的屬性值,類型是Object,而數組類型是Array;
數組是基於索引的實現,length會自動更新,而對象是鍵值對;
使用對象能夠建立僞數組,僞數組能夠正常使用數組的大部分方法;