a.變數類型 變數類型 構造函數 舉例 類型檢測typeof 字元串 function String() var t = "chua"; var m = new String("chua"); "string" 數字 function Number() var t = 12; var m = new
a.變數類型
變數類型 | 構造函數 | 舉例 |
類型檢測typeof |
字元串 | function String() |
var t = "chua"; var m = new String("chua"); |
"string" |
數字 | function Number() |
var t = 12; var m = new Number(12); |
"number" |
布爾 | function Boolean() |
var t = false; var m = new Boolean(0); var m1 = new Boolean(false); |
"boolean" |
數組 | function Array() |
var t = [1,2,3]; var m = new Array(1,2,3); var m1 = new Array(3); m1[0] = 1; m1[1] = 2; m1[2] = 3; |
"object" |
對象 | function Object() |
var t = {name:"chua"}; var m = new Object({name:"chua"}); var m1 = new Object(); m1.name = "chua"; |
"object" |
Null |
無,表示不該有值(無效值) ,null 被認為是對象的占位符 |
var t = null; //註意小寫 function m(name){ if(name == null){alert(name)} } m(null); //null |
"object" |
Undefined |
無,表示變數未初始化值 或函數中參數沒有傳遞 |
var t = undefined;//小寫 var tUn; alert(tUn);//undefined function m(name){ if(name == undefined){ alert("沒有傳遞參數") } } m();//"沒有傳遞參數" |
"undefined" |
函數(這算是一個 比較特殊的變數類型) |
function Function() |
var t = function(){}; //構造了一個名為t的函數 var m = new Function();/*t指向一個匿名函數, 目前Function無法構造擁有實體的函數 由此可見t和m根本就是兩回事,不等價*/ //匿名函數的寫法 (function(){}); //不加括弧運算符會報語法錯誤 //一個小運用 (function(){alert(1)})(); //1,構建匿名函數並馬上執行 (function(name){alert(name)})("chua"); //"chua",構建匿名函數並馬上執行 |
"function" |
日期類型 | function Date() |
var t = new Date();//獲取當前時間 var m = new Date("January 1,2000 22:00:00"); //設置一個時間 後面的備註會詳細簡介日期初始化的相容寫法 |
"object" |
正則類型 |
function RegExp(pattern, attributes) |
var t = /\d+/;//匹配一個或多個數字 var m = new RegExp("\\d+"); //更多正則表達式內容參考 http://blog.csdn.net/zaifendou/article/details/5746988 http://www.w3school.com.cn/jsref/jsref_obj_regexp.asp |
"object" |
Error類型 | function Error() |
var t = new Error("語法錯誤"); alert(t.message); //"語法錯誤" |
"object" |
註意:非廣義對象類型(函數,數組都屬於廣義對象類型)構造函數構造出來的變數是一個特殊的對象,只是在和其他非廣義對象類型比較的時候先轉化為非廣義對象類型在比較。所以
new String("chua") == "chua"; //true new String("chua") === "chua"; //false
Date初始化:
總的來說有三種初始化日期的方式得到了所有瀏覽器的支持:
1.字元串創建一個日期對象:
new Date("month dd,yyyy hh:mm:ss");
new Date("month dd,yyyy");
2.多個數字參數創建日期對象:
new Date(yyyy,mth,dd,hh,mm,ss);//其中mtd取值是0-11
new Date(yyyy,mth,dd);
3.使用毫秒創建日期
new Date(ms);//參數表示的是需要創建的時間和 GMT時間1970年1月1日之間相差的毫秒數
各種函數的含義如下:
month:用英文 表示月份名稱,從January到December
mth:用整數表示月份,從0(1月)到11(12月)
dd:表示一個 月中的第幾天,從1到31
yyyy:四位數表示的年份
hh:小時數,從0(午夜)到23(晚11點)
mm: 分鐘數,從0到59的整數
ss:秒數,從0到59的整數
ms:毫秒數,為大於等於0的整數
對於那些個位數來說,寫0x或x都可以
如:
new Date("January 1,2001 12:00:00");
new Date("January 1,2001");
new Date(2000,0,1,12,0,0);
new Date(2000,0,1);
new Date(978321600000);
上面的各種創建形式都表示2000年1月1日這一天。
未聲明的變數使用除typeof 之外的其他運算符的話,會引起錯誤,因為其他運算符只能用於已聲明的變數上。
表格中檢測類型看出,typeof只是廣義類型。如果想要檢測出變數真正的類型,可以參考jQuery的做法
var core_toString = {}.toString; core_toString.call([]); //"[object Array]" core_toString.call({}); //"[object Object]" core_toString.call(function(){}); //"[object Function]" core_toString.call(1); //"[object Number]" core_toString.call(""); //"[object String]" core_toString.call(new Date()); //"[object Date]" core_toString.call(/\d+/); //"[object RegExp]" core_toString.call(new Error()); //"[object Error]"
b.原始類型
原始值與引用值
在ECMAScript 中,變數可以存放兩種類型的值,即原始值和引用值。
原始值(primitive value)是存放在棧(stack)中的簡單數據欄位,也就是說,它們的值直接存儲在變數訪問的位置。 引用值(reference value)是存儲在堆(heap)中的對象,也就是說,存儲在變數出的值是一個指針(point),指向存儲對象的記憶體處。
ECMAScript 有 5 種原始類型(primitive type),即 Undefined、Null、Boolean、Number 和 String
這5種類型有些關鍵點需要註意
undefined:
undefined有幾個意義:變數定義(聲明)但是沒有賦值、函數調用中缺少的參數會被認為是undefined、當函數無明確返回值時返回的也是值 undefined
需要註意的是值 undefined 並不同於未定義(聲明)的值。但是,typeof 運算符並不真正區分這兩種值
var un; alert(typeof un); //"undefined" alert(typeof demo); //"undefined",變數demo並未定義
未定義的變數只能使用typeof這一個運算符,其他運算符都必須作用於已定義的變數
alert(demo2 == undefined); //會報錯,因為demo2未定義
null:
null 則用於表示尚未存在的對象(在討論 typeof 運算符時,簡單地介紹過這一點)。如果函數或方法要返回的是對象,那麼找不到該對象時,返回的通常是 null。
為什麼 typeof 運算符對於 null 值會返回 "Object"。這實際上是 JavaScript 的歷史遺留問題。現在,null 被認為是對象的占位符,從而解釋了這一矛盾,但從技術上來說,它仍然是原始值。
值 undefined 實際上是從值 null 派生來的,因此 ECMAScript 把它們定義為相等的
alert(null == undefined); //"true"
布爾類型:
false 不等於 0,0 也可以在必要時被轉換成 false,true和1同理。這樣在 Boolean 語句中使用兩者都是安全的。
alert(false == 0); //true alert(true == 1); //true alert(true == 11); //false alert(false == -1); //false
Number類型:
八進位字面量的首數字必須是 0,其後的數字可以是任何八進位數字(0-7);
十六進位的字面量,首位數字必須為 0,後面接字母 x,然後是任意的十六進位數字(0 到 9 和 A 到 F)。這些字母可以是大寫的,也可以是小寫的。
07; //7 011; //9 0xf; //15 0Xf; //15 0XF; //15
儘管所有整數都可以表示為八進位或十六進位的字面量,但所有數學運算返回的都是十進位結果
要定義浮點值,必須包括小數點和小數點後的一位數字(例如,用 1.0 而不是 1)
用科學計數法表示浮點數,可以把一個數表示為數字(包括十進位數字)加 e(或 E),後面加乘以 10 的倍數。
1.22e5; //122000 1.22e-5; //0.0000122
ECMAScript 預設把具有 6 個或 6 個以上前導 0 的浮點數轉換成科學計數法。
幾個特殊值也被定義為 Number 類型:
1. Number.MAX_VALUE 和 Number.MIN_VALUE,它們定義了 Number 值集合的外邊界。所有 ECMAScript 數都必須在這兩個值之間。不過計算生成的數值結果可以不落在這兩個值之間。
2.無窮大Number.POSITIVE_INFINITY與無窮小Number.NEGATIVE_INFINITY。兩者都表示值不再是數字了
使用isFinite() 判斷數值是否是有限的。
isFinite(Number.NEGATIVE_INFINITY); //false isFinite(Number.POSITIVE_INFINITY ); //false isFinite(Number.MAX_VALUE); //true isFinite(11); //true
3.NaN,表示非數(Not a Number)。NaN 是個奇怪的特殊值。一般說來,這種情況發生在類型(String、Boolean 等)轉換失敗時。例如字元串"chua" 轉換成數值就會失敗,因為沒有與之等價的數值。與無窮一樣,NaN 也不能用於算術計算。NaN 的另一個奇特之處在於,它與自身不相等:
NaN == NaN; // false
出於這個原因,不推薦使用 NaN 值本身。使用函數 isNaN判斷是否是非數值
alert(isNaN("chua")); // "true" alert(isNaN("666")); //"false"
String:
String類型是唯一沒有固定大小的原始類型。
c.變數聲明(這裡把函數類型也看成一個變數)
JS中變數聲明分顯式聲明和隱式聲明。
顯示聲明指使用使用var開頭的聲明(函數聲明除外)。
var t; //聲明一個變數為t function m(){}; //聲明一個名為m的函數
隱式聲明指沒有使用var明確聲明的變數。
a = 1;
需要註意的是隱式聲明並不是在執行代碼之前的聲明中聲明變數的,而是當執行到該代碼段時沒有查找到該變數,然後創建一個該作用域下的一個變數的,所以如果在變數表達式之前使用該變數則會報變數未定義的錯誤。
alert(b); //報錯,b未定義 b = 1; //聲明變數b,並給b賦值為1 alert(b); //1
所以隱式聲明是該語言的便利之處,不過如果不能緊密跟蹤變數,這樣做也很危險。最好的習慣是像使用其他程式設計語言一樣,總是聲明所有變數。
聲明變數的特點
1.無需明確的類型聲明
2.用同一個 var 語句定義的變數不必具有相同的類型
var name="chua",age=20;
3.不一定要初始化(它們是在幕後初始化的)
var name;
4.可以存放不同類型的值
var name = "chua; name = 11;
使用變數時,好的編碼習慣是始終存放相同類型的值。
變數命名
- 第一個字元必須是字母、下劃線(_)或美元符號($)
- 餘下的字元可以是下劃線、美元符號或任何字母或數字字元
d.變數申明在所有代碼執行之前
先看一個例子
var in_window = 'a' in window; alert(in_window);//true if (!("a" in window)) { var a = 1; }
alert(in_window)顯示true,很驚詫是不。
如果去掉var a = 1;這段代碼則alert(in_window)顯示為false。
我們再次來看一看標題:變數申明在所有代碼執行之前。
解析:腳本載入完成以後,瀏覽器掃描整個腳本,會將所有window下的顯示聲明(包括表達式中的聲明)的變數都先聲明,然後才執行表達式。
上面例子中聲明變數a是在表達式中聲明的,雖然表達式還沒有執行,但是聲明卻已經提前聲明瞭。當然,這個聲明表達式不能在函數中。如下
var in_window = 'a' in window; alert(in_window);//false function b(){ var a = 1; }
隱式聲明是不會提前聲明的,前面變數聲明已經分析。
剛纔那個是普通變數的顯示聲明,如果是函數的聲明呢?
var in_window = 'a' in window; alert(in_window);//IE/chrome顯示true,Firefox顯示false if (!("a" in window)) { function a(){} }
很遺憾的是IE/chrome會掃描全局作用域下表達式中的函數聲明並提前聲明,但是Firefox卻沒有。
所以這個沒有定論。Firefox會把判斷語句裡面的函數申明當成函數表達式(整個if判斷看成一個表達式),執行到那句話的時候才申明函數;chrome則會提前申明所有函數申明(包括類似var m = function(){…}這樣明顯是函數表達式的函數)。
但是一點可以肯定的是,函數申明和賦值是在聲明期間同時完成的,變數賦值語句是作為表達式來執行的。
var a = '1'; function a(){} alert(a); //1
解析步驟為先申明瞭一個變數a,然後是一個無效的申明(申明都提前了,同一個申明只會有一次),給a賦值為函數(函數申明是在申明過程中賦值),申明完成以後執行代碼表達式a = 1。所以結果為1。
function a(){}; var a; alert(a); //function a(){}
解析步驟就是先申明瞭一個變數,然後賦值為a函數,然後沒有然後了(申明都提前了,同一個申明只會有一次)。
var a = function () { return true }; var a;
alert(a); //function () { return true };
解析步驟就是先申明瞭一個變數為a, 然後是一個無效的申明(函數申明是在申明過程中賦值),申明完成以後執行表達式給a賦值為一個函數,然後沒有然後了(申明都提前了)。
這裡涉及幾個重要概念:
1 變數聲明在進入執行表達式之前就完成了
2 函數聲明也是提前的,所有的函數聲明都在執行代碼之前都已經完成了聲明,和變數聲明一樣
3 函數聲明會在申明的過程中就對申明的變數賦值為函數
但是我們不提倡在聲明變數的代碼之前使用該變數,這種寫法不直觀也不好維護。
如果覺得本文不錯,請點擊右下方【推薦】!