理解Javascript_04_數據模型

作者: 笨蛋的座右銘  來源: 博客園  發布時間: 2010-10-18 21:31  閱讀: 1242 次  推薦: 1   原文鏈接   [收藏]  

  本文主要描述Javascript的數據模型,即對Javascript所支持的數據類型的一個全局概纜。文章比較的理論化,非常深入,因此不易理解,但務必對數據模型有一個映象,因為他是理解Javascript對象模型與Javascript執行模型的基礎。

  基本的數據類型

  原始類型(簡單數據類型、基本數據類型)

  Undefined類型: 表示聲明了變量但未對其初始化時賦予該變量的值。undefined為Undefined類型下的唯一的一個值。

  Null類型:用于表示尚未存在的對象。Null類型下也只有一個專用值null。

  Boolean類型:有兩個值true和false,主要用于條件判斷,控制執行流程。

  Number類型:代表數字(即包括32的整數,也包括64位的浮點數)

  String類型:用于代表字符串。

  注:關于undefined與null的關系,可以參見《理解Javascript_02_理解undefined和null》一文。

  對象:一個無序屬性的集合,這些屬性的值為簡單數據類型、對象或者函數。注:這里對象并不特指全局對象Object.

  函數函數是對象的一種,實現上內部屬性[[Class]]值為"Function",表明它是函數類型,除了對象的內部屬性方法外,還有 [[Construct]]、[[Call]]、[[Scope]]等內部屬性。函數作為函數調用與構造器(使用new關鍵字創建實例對象)的處理機制不一樣(Function對象除外),內部方法[[Construct]]用于實現作為構造器的邏輯,方法[[Call]]實現作為函數調用的邏輯。同上,這里的函數并不特指全局對象Function。

  注:關于函數與對象的關系可以引申出很多問題,現在可以不去深究函數實現內部的細節,這將在以后的文章中探討。

  注:"基本的數據類型"與"基本數據類型"的概念不一樣,"基本的數據類型"指的是最常用的數據類型,"基本數據類型"指的是原始類型(關于原始類型與引用類型的問題,具體可以參見《理解Javascript_01_理解內存分配》一文)。

  內置數據類型(內置對象)

  Function: 函數類型的用戶接口。

  Object: 對象類型的用戶接口。

  Boolean, Number, String: 分別為這三種簡單數值類型的對象包裝器,對象包裝在概念上有點類似C#/Java中的Box/Unbox。

  Date, Array, RegExp: 可以把它們看作是幾種內置的擴展數據類型。

  首先,Function, Object, Boolean, Number, String, Date, Array, RegExp等都是JavaScript語言的內置對象,它們都可以看作是函數的派生類型,例如Number instanceof Function為true,Number instanceof Object為true。在這個意義上,可以將它們跟用戶定義的函數等同看待。

  其次,它們各自可以代表一種數據類型,由JS引擎用native code或內置的JS代碼實現,是暴露給開發者對這些內置數據類型進行操作的接口。在這個意義上,它們都是一種抽象的概念,后面隱藏了具體的實現機制。在每一個提到Number, Function等單詞的地方,應該迅速的在思維中將它們實例化為上面的兩種情況之一。

  數據類型實現模型描述

注:圖片來源于http://www.cnblogs.com/riccc

  Build-in *** data structure: 指JS內部用于實現***類型的數據結構,由宿主環境(瀏覽器)提供,這些結構我們基本上無法直接操作。

  Build-in *** object: 指JS內置的Number, String, Boolean等這些對象,這是JS將內部實現的數據類型暴露給開發者使用的接口。

  Build-in *** constructor: 指JS內置的一些構造器,用來構造相應類型的對象實例。它們被包裝成函數對象暴露出來,例如我們可以使用下面的方法訪問到這些函數對象:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
//access the build-in number constructor
var number = new Number(123);
var numConstructor1 = number.constructor; //or
var numConstructor2 = new Object(123).constructor;
//both numConstructor1 and numConstructor2 are the build-in Number constructor
numConstructor1 == numConstructor2 //result: true
//access the build-in object constructor
var objConstructor1 = {}.constructor; //or
var objConstructor2 = new Object().constructor;
//both objConstructor1 and objConstructor2 are the build-in Object constructor
objConstructor1==objConstructor2 //result: true

   關于"接口"的解釋:簡單的說,接口就是可以調用的方法。如:

//String就是一個接口,它定義了String的行為.它可以由外部調用
var str = new String('笨蛋的座右銘');
//我們自已定義一個接口
function say(msg){
   alert(msg);
}
//調用定義的接口
say("hello world");

  注:完全理解接口的概念需要有一定的強類型語言編程經驗(java/c#),因為本文已經夠復雜了,就不再將問題復雜化了。所以對于接口的答案并不是很嚴謹,但已經夠用了,望高人見諒。

  關于簡單數據類型的對象化

  這是一個細微的地方,下面描述對于Boolean, String和Number這三種簡單數值類型都適用,以Number為例說明。JS規范要求: 使用var num1=123;這樣的代碼,直接返回基本數據類型,就是說返回的對象不是派生自Number和Object類型,用num1 instanceof Object測試為false;使用new關鍵字創建則返回Number類型,例如var num2=new Number(123); num2 instanceof Number為true。

  將Number當作函數調用,返回結果會轉換成簡單數值類型。下面是測試代碼:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
var num1 = new Number(123); //num1 derived from Number & Object
num1 instanceof Number //result: true
num1 instanceof Object //result: true
//convert the num1 from Number type to primitive type, so it's no longer an instance of Number or Object
num1 = Number(num1);
num1 instanceof Number //result: false
num1 instanceof Object //result: false
var num2 = 123; //num2 is a primitive type
num2 instanceof Number //result: false
num2 instanceof Object //result: false

  結論:雖然我們得到了一個簡單數值類型,但它看起來仍然是一個JS Object對象,具有Object以及相應類型的所有屬性和方法,使用上基本沒有差別,唯一不同之處是instanceof的測試結果。由此也就產生了一個概念"Literal Syntax"

  Literal Syntax

  在簡單數據類型的對象化一節中,我們也看到了簡單類型和其包裝類型可以相互轉換,并且兩者之間的行為相同。但兩者相比較,明顯簡單類型的定義更加輕量,因此我們可以用簡單類型定義替換相應的包裝類型定義。如:

Number: var i = 100; //替代var i = new Number(100);
Boolean: var b = true;  //替代var b = new Boolean(true);
String: var str = 'this is a string.'; //替代var str = new String('this is a string');

  其實這種類似于var i = 100;var b=true;var str='this is a string'這種定義方式就叫做Literal Syntax。難道就只有簡單數據類型才有這種Literal Syntax的表示方法嗎!不是的,復合數據類型同樣有。

//對象定義的字面量表示法
var obj  = {name:'笨蛋的座右銘',age:25}
/*
//對象的非字面量表示法
var obj = new Object();
obj.name = '笨蛋的座右銘';
obj.age = 25;
*/

//數組定義的字面量表示法
var arr = ['笨蛋的座右銘',25];
/*
//數組的非字面量表示法
var arr = new Array();
arr[0]='笨蛋的座右銘'];
arr[1]=25;
*/

//正則表達式字面量表式法
var reg = /\d+/;
/*
//正則表達式非字面量表式法
var reg = new RegExp("\d+");
*/

  那函數呢!其實函數的定義已經是Literal Syntax的表示形式了。在實際工作中,我們建議盡量采用Literal Syntax的形式定義變量,因為這樣更簡單,更高效。

1
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

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