文章出處

  javascript中最經典也最受非議的一句話就是:javascript中一切皆是對象。這篇重點要提到的,就是任何jser都不陌生的Object和Array。

  有段時間曾經很詫異,到底兩種數據類型用來存儲數據有什么不同。于是,我打算探究探究。

 一、掌握三種數據類型

  首先,一個前提必須掌握的,就是必須理解javascript的數據類型分類,主要分為以下三種:

  第一種類型是標量(scalar),也就是一個單獨的字符串(string)或數字(numbers),比如"北京"這個單獨的詞。

  第二種類型是序列(sequence),也就是若干個相關的數據按照一定順序并列在一起,又叫做數組(array)或列表(List),比如"北京,上海"。

  第三種類型是映射(mapping),也就是一個鍵/值對(key/value),即數據有一個鍵名,還有一個與之相對應的鍵值,這又稱作散列/哈希(hash)或字典(dictionary),比如"首都:北京"。

  從這里也可知道對象就是一種映射類型的數據數組是一種序列類型的數據

  比較細致的解答,可以參考阮一峰的博文《數據類型和Json格式

  

 二、聲明和實例化方式

  1.對象的聲明和實例化  
  

//第一種方式
var obj = new Object();
obj.name = "wall";

//第二種方式
var obj = {};
obj.name = "wall";

//第三種方式
var obj = {
   "name" : "wall" 
};

//第三種方式的簡約版
var obj = {
   name : "wall" //key減少了一對雙引號
};

//第四種方式
var obj = {};
obj["name"] = "wall";

  

  2.數組的聲明和實例化

  

//第一種方式
var arr = new Array();
arr[0] = "wall";

//第二種方式
var arr = [];
arr[0] = "wall";

//第三種方式
var arr = ["wall"];

//第四種方式
var arr = [];
arr.push("wall");

//詭異的第五種方式,也是后面講的一個重點
var arr = [];
arr["name"] = "wall";

 三、使用方式

//輸出對象中name的值
console.log(obj.name);
//或
console.log(obj["name"]);

//輸出數組中name的值
console.log(arr[0]);

//輸出數組聲明的第五種方式中的值
console.log(arr["name"]);

 四、比較

  以上可以看出,其實在簡單的數據存儲要求上,選擇數組和選擇對象進行存儲,差別不是很大,而且兩者均可以用下標的方式進行訪問,所以有時自己都有疑惑到底二者區別到底在哪里。

  最簡單的不同就是:對象,系統默認是沒有length屬性的,而數組是默認有length屬性的。而這,又牽扯出一個有趣的現象:

  在chrome的控制臺下,輸出一個簡單的例子

  

 

  到這里,肯定會有人感到奇怪,為什么變量b的長度會是0! 為什么不是1。

  為了驗證我的想法,就再編寫一個例子:

  

  原來,b["test"]這個鍵值并沒有放入數組的序列中去,那會跑哪里去了?于是我查了下b這個變量的結構,然后再重新實例化一個新的變量b,比較其不同,終于找到原因:

                      

  原來,test是作為數組的一個屬性值進行存儲,而不是添加到數組的數據序列中去,頓時豁然開朗,呵呵~

  這里也可以得出一個結論:數組是一個可以存儲序列類型數據的對象,即是對對象的繼承和擴展。數組的序列類型數據,可以通過整數下標進行讀寫操作,而其自定義的屬性值,則可以通過對象訪問屬性值的方式進行訪問,二者互不干擾。

  五、對象實例化中需要注意的地方  

//第三種方式
var obj = {
   "name" : "wall" 
};

//第三種方式的簡約版
var obj = {
   name : "wall" //key減少了一對雙引號
};

  雖然這兩種方式看起來沒什么不同,都可以使用obj.name進行訪問,但是這里推薦第三種方式,而不要用簡約版。

  原因就是如果用簡約版的方式進行實例化,鍵名如果是javascript保留的關鍵字,在 ECMAScript 5 之前會拋出SyntaxError 的錯誤(來自javascript秘密花園的解釋)。

 六、函數變量緩存的技巧

  我就不多說,直接先上代碼:

//定義函數
var fun = function(options){
    if(!arguments.callee.arr){
      arguments.callee.arr = {
         "name":"wall",
         "who":"jser"        
      };
       console.log("init");//標識是否調用初始化
    }

    return arguments.callee.arr[options];
}    

//訪問name
console.log(fun("name"));

//訪問who
console.log(fun("who"));

  運行結果如下:

  所以,很明顯地,數據只要初始化一次,就會保存在當前函數對象下,作為它的一個屬性值,下次操作就可以避免重復性的工作了。

  可能很多讀者還不是很明白arguments.callee是什么,其實它指向的就是調用當前方法的對象,也即是fun。

  這樣寫的原因是,在實際生產過程中,多人協作編碼,可能有人會一不小心把你這里的function改個名字什么的,那緩存的作用就失效了,甚至會出錯。不過有個缺點就是在嚴格模式下,arguments.callee會被禁用。

  最后,再貼上一個未做上面這個優化的代碼,其實效果也一樣(其實就是將arguments.callee替換成fun)。

//定義函數
var fun = function(options){
    if(!fun.arr){
      fun.arr = {
         "name":"wall",
         "who":"jser"        
      };
       console.log("init");//標識是否調用初始化
    }

    return fun.arr[options];
}    

//訪問name
console.log(fun("name"));

//訪問who
console.log(fun("who"));

  另外,這里的arguments.callee也可以替換成this指針,不過,調用的時候就要注意this指針的指向,這里可以用new function()的方式調用。

 

via:cnblogs.com/walls/p/4281531.html 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()