本文中,將簡述JavaScript類型系統和數據類型,以及如何使用typeof操作符執行類型檢查。
還講解了使用typeof操作符進行某些數據類型檢查是不完善的,并介紹其他幾種類型檢查的方法。
每種編程語言都有自己的類型系統和數據類型,但各種編程語言的數據結構常有不同之處。使用JavaScript時,其引擎會在腳本執行期間隱式強制轉換執行值的類型。類型檢查對于編寫可預測的JavaScript程序是非常有必要的。
JavaScript中的typeof操作符就是用于基礎的類型檢查
typeof操作符返回字符串,表示未經計算的操作數的類型(來自MDN)
在此之前,需要了解JavaScript有哪些數據類型,最新標準定義了8種數據類型:
JavaScript還有幾個對象類構造函數,用于創建其他類型的對象:
1、語法
typeof使用一元操作符(只需要一個操作數)的計算結果作為其操作數的類型結果字符串。
另一種替代語法就是將操作數放入括號中使用,這種對JavaScript表達式返回的值進行類型檢查非常有用。
typeof 參數 typeof(參數)
參數:一個表示對象或原始值的表達式,其類型將被返回
typeof "sueRimn"; // 'string' typeof 22; // 'number' typeof NaN; // 'number' typeof Infinity; // 'number' typeof true; // 'boolean' typeof false; // 'boolean' typeof [1, 2]; // 'object' typeof {age: 22}; // 'object' typeof null; // 'object' typeof undefined; // 'undefined' typeof String; // 'function' typeof Boolean; // 'function' typeof Number; // 'function' typeof Object; // 'function' typeof Function; // 'function' typeof person; // 'function'
undefined是它自己的JavaScript類型
在ES6之前,typeof不管操作數是否聲明,總是返回一個字符串,即對于未聲明的標識符,總是返回而不是拋出錯誤。
在ES6中,使用let或const聲明的塊級作用域變量在初始化之前與typeof操作符使用,將拋出錯誤。
原因是:塊級作用域變量在被初始化之前一直保留在臨時死區。
console.log(typeof name==='undefined'); // ReferenceError const name='sueRimn';
2、一般類型檢查
在JavaScript中執行類型檢查主要使用typeof操作符
function add(a, b) { if (typeof a !=='number' || typeof b !=='number') { throw '參數必須是數值' } return a + b; }
以下是對類型檢查的簡單摘要:
檢測值是否存在在不同環境是這樣的:
if (typeof window !=='undefined') { // 瀏覽器 }; if (typeof process !=='undefined') { // Node.js } if (typeof $ !=='undefined') { // jQuery }
3、其他類型檢查
對于某些值需要額外的類型檢查才可以區分,例如null和[]在使用typeof操作符執行type-check時都是"object"類型,但是區分它們需要額外的操作。
一些其他數據類型值檢查方法:
(1)檢測是否為空
使用typeof操作符檢查值是否為空并不好,檢查值是否為空的最佳方法是對值與關鍵字進行嚴格相等比較。
以上代碼呈現的結果是不一樣的,所以使用嚴格相等操作符是非常重要的。
(2)檢測NaN
任何涉及NaN的算術運算都將對NaN求值,如果想為任何形式的算術運算使用值,那么需要確保該值不是NaN。
使用typeof操作符檢查NaN值是否返回"number"。要檢查NaN值,可以使用全局函數isNaN(),或者ES6中的Number.isNaN()函數:
NaN值非常特殊,通過比較,它永遠不等于任何其他值,包括它自己:
可以使用以下方法在非ES6環境下檢測NaN:
function isNan(value) { return value !==value; }
最后,你可以利用ES6中的Object.is()函數來測試值是否為NaN。
以下函數作用是檢查兩個值是否相同:
function isNan(value) { return Object.is(value, Number.NaN); }
(3)檢測數組
使用typeof檢查數組將返回object。這里介紹幾種檢測數組的方法,并進行對比:
function isArray(value) { return typeof value=='object' && value.constructor===Array; }
function isArray(value) { return value instanceof Array; }
function isArray(value) { return Object.prototype.toString.call(value)==='[object Array]'; }
object.prototype.tostring()方法對于檢查任何JavaScript值的對象類型都非常有用
量的數據類型轉換:將一種數據類型轉換為另外一種數據類型。
通常有三種形式的類型轉換:
你會專門把某個數據類型轉換成 null 或者 undefined 嗎?不會,因為這樣做,沒有意義。
我們先來講一下 typeof,再講類型轉換。
typeof()表示“獲取變量的數據類型”,返回的是小寫,語法為:(兩種寫法都可以)
// 寫法1typeof 變量;// 寫法2typeof(變量);
typeof 這個運算符的返回結果就是變量的類型。那返回結果的類型是什么呢?是字符串。
返回結果:
typeof 的代碼寫法返回結果typeof 數字numbertypeof 字符串stringtypeof 布爾型booleantypeof 對象objecttypeof 方法functiontypeof nullobjecttypeof undefinedundefined
備注 1:為啥 typeof null的返回值也是 object 呢?因為 null 代表的是空對象。
備注 2:typeof NaN的返回值是 number,上一篇文章中講過,NaN 是一個特殊的數字。
返回結果舉例:
console.log(type []); // 空數組的打印結果:objectconsole.log(type {}); // 空對象的打印結果:object
代碼解釋:這里的空數組[]、空對象{} ,為啥他們在使用 typeof 時,返回值也是 object呢?因為這里的 返回結果object指的是引用數據類型。空數組、空對象都是引用數據類型 Object。
類型轉換分為兩種:顯示類型轉換、隱式類型轉換。
針對上面這兩種類型轉換,這篇文章來詳細介紹。
格式:變量+”” 或者 變量+”abc”
舉例:
var a=123; // Number 類型console.log(a + ''); // 轉換成 String 類型console.log(a + 'haha'); // 轉換成 String 類型
上面的例子中,打印的結果,都是字符串類型的數據。實際上內部是調用的 String() 函數。也就是說,c=c + "" 等價于 c=String(c)。
語法:
變量.toString()
【重要】該方法不會影響到原變量,它會將轉換的結果返回。當然我們還可以直接寫成a=a.toString(),這樣的話,就是直接修改原變量。
注意:null 和 undefined 這兩個值沒有 toString()方法,所以它們不能用方法二。如果調用,會報錯。
另外,Number 類型的變量,在調用 toString()時,可以在方法中傳遞一個整數作為參數。此時它將會把數字轉換為指定的進制,如果不指定則默認轉換為 10 進制。例如:
var a=255;//對于Number調用toString()時可以在方法中傳遞一個整數作為參數//此時它將會把數字轉換為指定的進制,如果不指定則默認轉換為10進制a=a.toString(2); // 轉換為二進制console.log(a); // 11111111console.log(typeof a); // string
語法:
String(變量)
使用 String()函數做強制類型轉換時:
我們在 JS 基礎的第 01 篇里,就講過,prompt()就是專門用來彈出能夠讓用戶輸入的對話框。重要的是:用戶不管輸入什么,都當字符串處理。
情況一:字符串 —> 數字
情況二:布爾 —> 數字
情況三:null —> 數字
情況四:undefined —> 數字
補充:怎么理解這里的 NaN 呢?可以這樣理解,使用 Number() 函數之后,如果無法轉換為數字,就會轉換為 NaN。
parseInt()的作用是將字符串中的有效的整數內容轉為數字。parse 表示“轉換”,Int 表示“整數”(注意Int的拼寫)。例如:
parseInt("5");
得到的結果是數字 5。
parseInt()的轉換情況如下。
情況一:字符串 —> 數字
情況二:Boolean —> 數字
情況三:Null —> 數字
情況四:Undefined —> 數字
Number() 函數和 parseInt() 函數的區別:
就拿Number(true) 和 parseInt(true)/parseFloat(true)來舉例,二者在使用時,是有區別的:
parseInt()具有以下特性:
(1)只保留字符串最開頭的數字,后面的中文自動消失。例如:
console.log(parseInt("2017在公眾號上寫了6篇文章")); //打印結果:2017console.log(parseInt("2017.01在公眾號上寫了6篇文章")); //打印結果仍是:2017 (說明只會取整數)console.log(parseInt("aaa2017.01在公眾號上寫了6篇文章")); //打印結果:NaN (因為不是以數字開頭)
(2)如果對非 String使用 parseInt()或 parseFloat(),它會先將其轉換為 String 然后再操作。【重要】
比如:
var a=168.23;console.log(parseInt(a)); //打印結果:168 (因為是先將c轉為字符串"168.23",然后然后再操作)var b=true;console.log(parseInt(b)); //打印結果:NaN (因為是先將a轉為字符串"true",然后然后再操作)var c=null;console.log(parseInt(c)); //打印結果:NaN (因為是先將b轉為字符串"null",然后然后再操作)var d=undefined;console.log(parseInt(d)); //打印結果:NaN (因為是先將b轉為字符串"undefined",然后然后再操作)
(3)自動帶有截斷小數的功能:取整,不四舍五入。
例 1:
var a=parseInt(5.8) + parseInt(4.7);console.log(a);
打印結果:
9
例 2:
var a=parseInt(5.8 + 4.7);console.log(a);
打印結果:
10;
(4)帶兩個參數時,表示在轉換時,包含了進制轉換。
代碼舉例:
var a='110';var num=parseInt(a, 16); // 【重要】將 a 當成 十六進制 來看待,轉換成 十進制 的 numconsole.log(num);
打印結果:
272
如果你對打印結果感到震驚,請仔細看上面的代碼注釋。就是說,無論 parseInt() 里面的進制參數是多少,最終的轉換結果是十進制。
我們繼續來看下面的代碼,打印結果是多少。
var a='5';var num=parseInt(a, 2); // 將 a 當成 二進制 來看待,轉換成 十進制 的 numconsole.log(num); // 打印結果:NaN。因為 二進制中沒有 5 這個數,轉換失敗。
parseFloat()的作用是:將字符串轉換為浮點數。
parseFloat()和 parseInt()的作用類似,不同的是,parseFloat()可以獲得有效的小數部分。
代碼舉例:
var a='123.456.789px';console.log(parseFloat(a)); // 打印結果:123.456
parseFloat() 的幾個特性,可以參照 parseInt()。
將其他的數據類型轉換為 Boolean,可以使用 Boolean()函數。情況如下:
PS:轉換為 Boolean 的這幾種情況,很重要,開發中會經常用到。
比如070這個字符串,如果我調用 parseInt()轉成數字時,有些瀏覽器會當成 8 進制解析,有些會當成 10 進制解析。
所以,比較建議的做法是:可以在 parseInt()中傳遞第二個參數,來指定當前數字的進制。例如:
var a="070";a=parseInt(a, 8); //將 070 當成八進制來看待,轉換結果為十進制。console.log(a); // 打印結果:56。這個地方要好好理解。
重點:隱式類型轉換,內部調用的都是顯式類型的方法。下面來詳細介紹。
語法:
isNaN(參數);
解釋:判斷指定的參數是否為 NaN(非數字類型),返回結果為 Boolean 類型。也就是說:任何不能被轉換為數值的參數,都會讓這個函數返回 true。
執行過程:
(1)先調用Number(參數)函數;
(2)然后將Number(參數)的返回結果和NaN進行比較。
代碼舉例:
console.log(isNaN('123')); // 返回結果:false。console.log(isNaN('abc')); // 返回結果:true。因為 Number('abc') 的返回結果是 NaNconsole.log(isNaN(null)); // 返回結果:falseconsole.log(isNaN(undefined)); // 返回結果:trueconsole.log(isNaN(NaN)); // 返回結果:true
舉例 1:
var a="666";a++;console.log(typeof a); // 打印結果: numberconsole.log(a); // 打印結果:667
執行過程:
(1)先調用Number(參數)函數;
(2)然后將Number(參數)的返回結果進行 加 1 操作。
舉例 2:
var a='abc';a++;console.log(typeof a); // 打印結果:numberconsole.log(a); // 打印結果:NaN。因為 Number('abc')的結果為 NaN,再自增后,結果依然是 NaN
注意,這里說的是正號/負號,不是加號/減號。
任何值做+a、-a、/a運算時,運算結果都會自動轉換為 Number 類型。 內部調用的是 Number() 函數。
舉例:
var a='666';var b=+a;console.log(typeof a); // 打印結果:string。說明 a 的數據類型保持不變。console.log(a); // 打印結果:666console.log(typeof b); // 打印結果:number。說明 b 的數據類型發生了變化。console.log(b); // 打印結果:666
情況一:字符串 + 數字
情況二:Boolean + 數字
情況三: null + 數字
情況四: undefined + 數字
1、任何非 Number 類型的值做-、*、/運算時,會將這些值轉換為Number然后再運算(內部調用的是 Number() 函數),運算結果是 Number 類型。(注:任何值 + 字符串是特例,運算結果是字符串)
比如:
result1=true + 1; // 2=1+ 1 result2=true + false; // 1=1+ 0 result3=1 + null; // 1=1+ 0 result4=100 - '1' // 99
2、任何的值和字符串做加法運算,都會先轉換為字符串,然后再做拼串操作。
比如:
result1=1 + 2 + '3' // 33 result2='1' + 2 + 3; // 123
3、任何值和NaN做運算的結果都是NaN。
頁可見區域寬:document.body.clientWidth
網頁可見區域高:document.body.clientHeight
網頁可見區域寬:document.body.offsetWidth (包括邊線的寬)
網頁可見區域高:document.body.offsetHeight (包括邊線的寬)
網頁正文全文寬:document.body.scrollWidth
網頁正文全文高:document.body.scrollHeight
網頁被卷去的高:document.body.scrollTop
網頁被卷去的左:document.body.scrollLeft
網頁正文部分上:window.screenTop
網頁正文部分左:window.screenLeft
屏幕分辨率的高:window.screen.height
屏幕分辨率的寬:window.screen.width
屏幕可用工作區高度:window.screen.availHeight
屏幕可用工作區寬度:window.screen.availWidth
HTML精確定位:scrollLeft,scrollWidth,clientWidth,offsetWidth
scrollHeight: 獲取對象的滾動高度。
scrollLeft:設置或獲取位于對象左邊界和窗口中目前可見內容的最左端之間的距離
scrollTop:設置或獲取位于對象最頂端和窗口中可見內容的最頂端之間的距離
scrollWidth:獲取對象的滾動寬度
offsetHeight:獲取對象相對于版面或由父坐標 offsetParent 屬性指定的父坐標的高度
offsetLeft:獲取對象相對于版面或由 offsetParent 屬性指定的父坐標的計算左側位置
offsetTop:獲取對象相對于版面或由 offsetTop 屬性指定的父坐標的計算頂端位置
event.clientX 相對文檔的水平座標
event.clientY 相對文檔的垂直座標
event.offsetX 相對容器的水平坐標
event.offsetY 相對容器的垂直坐標
document.documentElement.scrollTop 垂直方向滾動的值
event.clientX+document.documentElement.scrollTop 相對文檔的水平座標+垂直方向滾動的量
IE,FireFox 差異如下:
IE6.0、FF1.06+:
clientWidth=width + padding
clientHeight=height + padding
offsetWidth=width + padding + border
offsetHeight=height + padding + border
IE5.0/5.5:
clientWidth=width - border
clientHeight=height - border
offsetWidth=width
offsetHeight=height
(需要提一下:CSS中的margin屬性,與clientWidth、offsetWidth、clientHeight、offsetHeight均無關)
網頁可見區域寬: document.body.clientWidth
網頁可見區域高: document.body.clientHeight
網頁可見區域寬: document.body.offsetWidth (包括邊線的寬)
網頁可見區域高: document.body.offsetHeight (包括邊線的高)
網頁正文全文寬: document.body.scrollWidth
網頁正文全文高: document.body.scrollHeight
網頁被卷去的高: document.body.scrollTop
網頁被卷去的左: document.body.scrollLeft
網頁正文部分上: window.screenTop
網頁正文部分左: window.screenLeft
屏幕分辨率的高: window.screen.height
屏幕分辨率的寬: window.screen.width
屏幕可用工作區高度: window.screen.availHeight
屏幕可用工作區寬度: window.screen.availWidth
-------------------
技術要點
本節代碼主要使用了Document對象關于窗口的一些屬性,這些屬性的主要功能和用法如下。
要得到窗口的尺寸,對于不同的瀏覽器,需要使用不同的屬性和方法:若要檢測窗口的真實尺寸,在Netscape下需要使用Window的屬性;在IE下需要 深入Document內部對body進行檢測;在DOM環境下,若要得到窗口的尺寸,需要注意根元素的尺寸,而不是元素。
Window對象的innerWidth屬性包含當前窗口的內部寬度。Window對象的innerHeight屬性包含當前窗口的內部高度。
Document對象的body屬性對應HTML文檔的標簽。Document對象的documentElement屬性則表示HTML文檔的根節點。
document.body.clientHeight表示HTML文檔所在窗口的當前高度。document.body. clientWidth表示HTML文檔所在窗口的當前寬度。
實現代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>請調整瀏覽器窗口</title>
<meta http-equiv="content-type" content="text/html; charset=gb2312">
</head>
<body>
<h2 align="center">請調整瀏覽器窗口大小</h2><hr>
<form action="#" method="get" name="form1" id="form1">
<!--顯示瀏覽器窗口的實際尺寸-->
瀏覽器窗口 的 實際高度: <input type="text" name="availHeight" size="4"><br>
瀏覽器窗口 的 實際寬度: <input type="text" name="availWidth" size="4"><br>
</form>
<script type="text/javascript">
<!--
var winWidth=0;
var winHeight=0;
function findDimensions() //函數:獲取尺寸
{
//獲取窗口寬度
if (window.innerWidth)
winWidth=window.innerWidth;
else if ((document.body) && (document.body.clientWidth))
winWidth=document.body.clientWidth;
//獲取窗口高度
if (window.innerHeight)
winHeight=window.innerHeight;
else if ((document.body) && (document.body.clientHeight))
winHeight=document.body.clientHeight;
//通過深入Document內部對body進行檢測,獲取窗口大小
if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientWidth)
{
winHeight=document.documentElement.clientHeight;
winWidth=document.documentElement.clientWidth;
}
//結果輸出至兩個文本框
document.form1.availHeight.value=winHeight;
document.form1.availWidth.value=winWidth;
}
findDimensions();
//調用函數,獲取數值
window.onresize=findDimensions;
//-->
</script>
</body>
</html>
源程序解讀
(1)程序首先建立一個表單,包含兩個文本框,用于顯示窗口當前的寬度和高度,并且,其數值會隨窗口大小的改變而變化。
(2)在隨后的JavaScript代碼中,首先定義了兩個變量winWidth和winHeight,用于保存窗口的高度值和寬度值。
(3)然后,在函數findDimensions ( )中,使用window.innerHeight和window.innerWidth得到窗口的高度和寬度,并將二者保存在前述兩個變量中。
(4)再通過深入Document內部對body進行檢測,獲取窗口大小,并存儲在前述兩個變量中。
(5)在函數的最后,通過按名稱訪問表單元素,結果輸出至兩個文本框。
(6)在JavaScript代碼的最后,通過調用findDimensions ( )函數,完成整個操作。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。