看過jQuery源碼的人都知道類數組對象,與我們熟知的arguments對象很像
構造一個類數組必須有兩個條件
第一個條件:你必須給對象定義個splice方法,只要他是一個function就可以
第二個條件:就是賦值一個length屬性,或者增加push,unshift,shift,pop其中任何一個方法,並且調用了一次。
當這兩個條件同時滿足那么當前的對象在控制台輸出后跟數組的格式一模一樣。
一般而言大部分都是這樣構造一個類數組對象(jQuery就是這么干的)。因為相比而言,這樣更簡潔,並且更有意義。
1 var obj = { 2 length: 0, 3 splice: [].splice 4 };
同樣可以實現類數組的代碼,除了splice,其他四個方法只要定義了其中的任何一個並且調用了。
1 var blankArray = []; 2 var obj = { 3 splice: blankArray.splice, 4 push: blankArray.push, 5 unshift: blankArray.unshift, 6 pop: blankArray.pop, 7 shift: blankArray.shift 8 }; 9 obj.push(); 10 obj.unshift(); 11 obj.pop(); 12 obj.shift();
那為什么瀏覽器會這么做?其實我也不明白,因為我沒看過瀏覽器的內部實現,這個誰要知道的話,煩請告訴我一下。
----------------------------------------分割線------------------------------------
可能有些人不太明白直接把push指向數組的push方法就能直接調用,並且行為還和數組一樣?
是的,push本身就是給數組追加值的,在對象中這里也是一樣的,他會先檢測length屬性的值,然后從length的位置添加push傳的參數。key從length之后開始累加,同時更改length值。來段代碼說明下
1 var obj = { 2 length: 1, 3 splice: blankArray.splice, 4 push: blankArray.push 5 } 6 obj[0] = 10; //如果length是0的話,push后的結果就是1,2,3。如果length是1的話,那么結果就成了10,1,2,3。 7 8 obj.push(1,2,3);
9 obj.length // 4
由此看出,對象這里的obj[0] = 10並不會影響length的值,而數組卻不同,他會影響length的值。
你可以把數組的下標想象成對象的key
不理解?看下面的代碼
1 var testArr = ['one', 'two', 'three']; 2 3 //可以把以上數組理解成下面這種對象 4 5 var testObj = { 6 0: 'one', 7 1: 'two', 8 2: 'three' 9 }
接下來就簡單了,obj的push引用了array實例對象的push方法
1 var obj = { 2 // ... 3 //事實上[].push這里引用的是function push() { [native code] },push方法的內部實現 4 push: [].push 5 }
而引用的這個push function,它的context就是obj,與下面的代碼意義相同
1 var obj = { 2 push: function(){ 3 return [].push.apply(this, arguments); 4 } 5 }
在用下標值訪問類數組對象的時候,實際上訪問的是它的key。
個人理解,不對請指出。
轉載請注明出處。