數據類型
- ECMAScript中6大原始數據類型:字符串(
String
)Boolean
、Null
、Undefined
、Number
、Object
、Symbol
(es6新增)。(Object
——本質是由一組無序的名值對組成的復雜數據類型) - ECMAScript中5中簡單數據類型(基本數據類型):
String
、Boolean
、Null
、Undefined
、Number
typeof操作符
typeof操作符可能返回下列某個字符串:
-
"undefined"
—— 值未定義 "boolean"
-
"string"
(小寫) "number"
-
"object"
—— 這個值是對象或者null
"function"
var message = "some string";
alert(typeof message); //"string"
alert(typeof(message)); //"string"
alert(typeof 95); //"number"
typeof (new String("sdsd")) //"object"
typeof "sdsd" ///"string"
ECMAScript松散類型——需要
typeof
檢測給定變量數據類型
typeof null
會返回"object"
。因為特殊值"null"被認為是一個空的對象引用。
undefined
undefined
類型只有一個值,即特殊的undefined
。聲明后未初始化。
對于未初始化變量、未聲明變量、沒傳遞值的命名參數、沒有返回值的立即執行函數。執行typeof操作都是返回"undefined"
題目:假設 output 是一個函數,輸出一行文本。下面的語句輸出結果是什么?
output(typeof (function() {output(“Hello World!”)})());
// Hello World!undefined
分析:
1.先立即執行匿名函數,輸出Hello World!
2.函數執行后無返回值,則輸出未定義
var message;
alert(typeof message); //undefined
alert(typeof age); //undefined
null
null
也是只有一個值的數據類型,特殊值是null
。從邏輯角度上看,null值表示一個空對象指針,而這也正是使用typeof操作符檢測null值會返回“object
”的原因。
alert(null == undefined); //true
alert(null === undefined); //false
這里,位于null和undefined之間的相等操作符(==)總是返回true。具體可參考——"==" 與 "==="區別
盡管null和undefined有這樣的關系,但它們的用途完全不同。如前所述,無論在什么情況下都沒有必要把一個變量顯式地設置為undefined,可是同樣的規則對null卻不適用。換句話說,只要意在保存對象的變量還沒有真正保存對象,就應該明確地讓該變量保存null值。這樣做不僅可以體現null作為空對象指針的慣例,而且也有助于進一步區分null和undefined。
Boolean類型
該類型只有兩個字面值:true
和false
。這2個值跟數字值不是同一回事,因為true不一定等于1,false不一定等于0。該類型的2個值是區分大小寫的
雖然Boolean類型只有兩個字面值,但ECMAScript所有類型的值都有與這兩個Boolean值等價的值。要將一個值轉換為其對應的Boolean值,可以調用轉型函數Boolean()
。
轉換規則:
數據類型 | 轉換為true | 轉換為false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | ""(空字符串) |
Number | 任何非零數值(包括無窮大) | 0、+0、-0和NaN |
Object | 任何對象 | null |
Undefined | - | undefined |
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true
- 所有對象的布爾值都是
true
,js語言設計的時候出于性能考慮,,如果對象需要計算才能得到布爾值,對于obj1 && obj2
這樣的場景,可能會需要較多的計算。為了保證性能,就統一規定,對象的布爾值為true。
具體可參考——數據類型轉換
Number類型
最基本的數值字面量是10進制整數。除此之外,整數還可以用8進制、16進制的字面量表示。
其中,8進制首位必須是0,如果字面值超出范圍(超出0-7),前導0將被忽略,后面數值當做十進制數值解析。
16進制前面必須是0x
。后面是(0-9或A-F或a-f)。
var num1 = 070; //8進制的56
var num2 = 079; //無效8進制——解析為79
var num2 = 08; //無效8進制——解析為8
var hexnum1 = 0xA; //16進制10
var hexnum1 = 0x1f; //16進制31
- 8進制字面量在嚴格模式下無效,引擎拋錯。
浮點數值
所謂浮點數值——該數值必須包含一個小數點,且小數點后面至少有一位數字。(保存浮點數值需要內存空間是保存整數值的兩倍,ECMAScript會不失時機的將浮點數值轉換為整數值)
var floatNum1 = 1.; //解析為1
var floatNum2 = 10.0; //整數——解析為10
var floatNum3 = 3.125e7; //31250000
var floatNum4 = 3e-7; //0.0000003
//默認情況下,ECMAScript會將小數點后面帶有6個0以上浮點數值轉換為e表示法
浮點數值的最高精度是17位小數,但在進行算術計算時其精確度遠不如整數。例如,0.1
加0.2
的結果不是0.3
,而是0.300000000000000004
,這個小小的舍入誤差會導致無法測試特定的浮點數值。
var a=0.2,b=0.1;
if(a+b==0.3){
console.log("you got 0.3.");
}
我們測試這兩個數的和不等于3,如果這2個數是0.25和0.05,或者是0.15和0.15,結果都是沒有問題的。如果是0.1和0.2,那么測試無法通過。因此,永遠不要測試某個特定的浮點數值。
數值轉換
Number(), parseInt(),parseFloat()
Number()
函數的轉換規則如下:
- 如果boolean值,true和false將分別被轉換為1和0
- 如果是數字值,只是簡單的傳入和返回
- 如果是null值,返回0
- 如果是undefined,返回NaN
- 如果是字符串,包含其他字符,NaN。空字符串則為0。
- 如果是對象,與
isNaN()
方法類似
Number()
函數在轉換字符串的時候比較復雜不合理,所以常用parseInt()
函數
parseInt()
函數的轉換規則如下:
- 忽略字符串前面空格,直到找到第一個非空格字符。若第一個字符不是數字字符或者負號,返回NaN。
- 第一個字符是數字字符,繼續解析第二個字符......
- 可以識別16進制整數格式
- 參數二: 轉換時使用的技術(多少進制)
var num1 = parseInt("1234blue"); //1234
var num2 = parseInt(""); //NaN Numebr("") => 0
var num3 = parseInt("0xA"); //10
var num4 = parseInt(22.5); //22
var num5 = parseInt("070");
//ECMAScript5引擎中(無論是否嚴格):70 - 10進制
//ECMAScript3引擎中:56 - 8進制
var num6 = parseInt("70"); //70
var num7 = parseInt("0xf"); //15
var num7 = parseInt("0xaf", 16); //175
var num8 = parseInt("af", 16); //175
var num9 = parseInt("af"); //NaN
數值范圍
Numebr.MIN_VALUE
Number.MAX_VALUE
-
Number.NEGATIVE_INFINITY
——負無窮 -
Number.POSITIVE_INFINITY
——正無窮
NaN
NaN的兩個特點,一是任何涉及NaN的操作(例如NaN/10)都會返回NaN,這個特點在多步計算中有可能導致問題。其次,NaN與任何值都不相等,包括NaN本身。
任何數值除以0都返回NaN。
isNaN()
函數接收一個參數,該參數可以是任何類型,而函數會幫我們確定這個參數是否“不是數值”,isNaN()在接收這個值后,會嘗試將這個值轉換為數值。而任何不能被轉換為數值的值都會導致這個函數返回true。
isNaN()
同樣適用于對象。先調用對象的valueOf()
方法,然后確定該方法返回值能否可以轉換為數值。如果不能,則基于這個返回值再調用toString()
方法,再測試返回值。
alert(NaN==NaN); // false
alert(isNaN(isNaN)); // true
alert(isNaN(10)); // false
alert(isNaN("10")); // false
alert(isNaN("blue")); // true
alert(isNaN(true)); // false
String
字符字面量:包含特殊字面量(轉義序列),如:\n(換行)
、\t(制表)
、\b(空格)
、\\(斜杠)
、\unnnn(Unicode字符)
、\xnn
等。
var text = "13 2\u03a3.";
console.log(text.length); //6
字符串特點:不可變。一旦創建,值不能改變,改變某個變量所存的字符串,先銷毀原來的字符串,再用包含新值字符串填充。
var lang = "Java";
lang = lang + "Script";
//首先創建一個能容納10個字符的新字符串,然后再這個字符串中填充"Java"和"Script",最后一步銷毀原來的字符串"Java"和"Script"。上述過程,在后臺發生。
轉換為字符串:
- 幾乎每個值(包括字符串本身-返回副本。但不保括
undefined
和null
)都有的toString()
方法。數值調用時,該方法可帶參數——指定輸出數值基數。 -
String()
函數(不知道是否是null
或者undefined
情況下用)。 - 與字符串
""
相加。
//1.數值、布爾、對象、字符串(返回副本)都有toString方法。
var age = 11;
var ageString = age.toString(); //"11"
var found = true;
var foundString = found.toString(); //"true"
var num = 10;
alert(num.toString(2)); //"1010"
alert(num.toString(8)); //"12"
//2.String()規則:優先使用toString()。其次,null和undefined返回"null"和"undefined"
var val1;
alert(String(10)); //"10"
alert(String(true)); //"true"
alert(String(null)); //"null"
alert(String(val1)); // "undefined"
Object類型
Object的每個實例具有下列屬性和方法。
-
constructor
:保存著用于創建當前對象的函數。類似Object()
。 -
hasOwnProperty(propertyName)
:檢查給定的屬性在當前的對象實例(不是實例原型)中是否存在。參數必須是字符串,如o.hasOwnProperty("name")
。 -
isPrototypeOf(object)
:用于檢查傳入的對象是否是傳入對象的原型。 -
propertyIsEnumerable(propertyName)
:用于檢查給定的屬性能否能夠使用for-in語句來枚舉。參數必須是字符串。 -
toLocaleString()
:返回對象的字符串表示。與執行環境的地區對應。 -
toString()
:返回對象字符串表示。 -
valueOf()
:返回對象的字符串、數值或布爾值表示。通常與toString()
方法返回的值相同。
函數
-
參數
- 命名的參數只提供便利,但不是必需。函數體內通過
arguments
對象(類數組)來訪問參數數組。ECMAScript函數不在乎傳遞參數的個數以及類型。即便定義的函數直接收兩個參數,在調用時可以傳0,1,2,3個...... -
arguments
對象可以和命名參數一起使用。 -
arguments
的值永遠與命名參數的值保持同步。只是自動反映,但不是說這兩個值會訪問相同的內存空間,它們的內存空間獨立。 - 沒有傳遞值的命名參數將自動被賦予
undefined
的值。 - 嚴格模式下,重寫
arguments
的值會導致語法錯誤。上述第三點也會無效。
- 命名的參數只提供便利,但不是必需。函數體內通過
function fun(){
alert(arguments.lenght);
}
fun(); //0
fun1(1); //1
fun2(1,2,3); //3
//擬補重載缺陷
function add(num1, num2){
if(arguments.length == 1){
return arguments[0] + 10;
}
else if(argument.length == 2){
return arguments[0] + arguments[1];
//arguments對象可以和命名參數一起使用:return arguments[0] + num2;
}
}
//
function doAdd(num1, num2){
arguments[1] = 10;
return num1 + num2;
}
doAdd(1,2); //11 ===> 嚴格模式下報錯
-
沒有重載,重復只會覆蓋。
看到這想起一道面試題目,題目如下:
<script>
var m = 1, j = k = 0;
function add(n){
return n = n + 1;
}
y = add(m);
function add(n){
return n = n + 3;
}
z = add(m);
//問:y和z的最終結果是:4,4
</script>
說明:
- js里面沒有函數重載的概念。在其他語言(如java)中,可以存在同名函數,只要傳入參數數量或者類型不同即可。但是在js中,定義兩個同名函數后,后面的函數會覆蓋前面定義的函數。結合這道題來說,由于函數聲明提升,所以函數聲明會提前,由于存在同名函數。后面的
add
函數將覆蓋第一個add
函數。- 疑問:函數里
return
把參數改變了,為什么z不是7?——在ECMAScript中所有參數傳遞都是值傳遞,不可能通過引用傳遞參數。用完一次就銷毀了,下次重新傳值。
所以在本題中,前后兩次調用add()
返回的值是相同的,都是4。
更多解析請參考——鏈接
* 可以通過`arguments`對象檢查傳入參數中的類型和數量作出不同反應,模仿方法重載。
* 未指定特殊返回值的函數返回的是一個特殊的`undefined`值