JavaScript之類型

內置類型

JavaScript中有其中內置類型javascript

  1. 空值(null)
  2. 未定義(undefined)
  3. 布爾值(boolean)
  4. 數字(number)
  5. 字符串(string)
  6. 對象(object)
  7. 符號(symbol, ES6新增)
    在javascript中能夠用typeof運算符來查看值的類型,他返回的是類型的字符串值。
typeof null === "object"; //true
typeof undefined === "undefined"; //true
typeof true === "boolean"; //true
typeof 42 === "number"; //true
typeof "42" === "string"; //true
typeof {life: 42} === "object"; //true
typeof Symbol() === "symbol"; //true

以上除了null類型以外,其餘的六種類型均有同名的字符串值與之對應,而且null是基本類型中惟一的一個假值類型,typeof對他的返回值是object
除了上述的內置類型,還有一種狀況java

typeof function a(){} === 'function'; //true

如此看來,function(函數)也是javascript中的一個內置類型,可是經過instanceof這個屬性能夠發現,實際上它是object的一個子類型,具體來講,能夠把函數看成可調用對象,他是一個內部屬性[[call]], 該屬性使其能夠被調用,既然是對象,那函數也有本身的屬性,函數對象的length屬性是其聲明的參數的個數數組

function a(b, c){}
a.length; //2

值和引用

在javascript中,變量可能包含兩種不一樣數據類型的值,基本類型值和引用類型值。
基本類型值指的是簡單的數據段: 老是經過值複製的方式來賦值/傳遞,包括null,undefined,字符串,數字,布爾和ES6中的symbol
引用類型值指那些可能有多個值構成的對象(包括數組和封裝對象和函數),則老是經過引用複製的方式來賦值/傳遞
值複製:從一個變量像另外一個變量複製基本類型的值,會在變量對象上建立一個新值,而後將該值複製到爲新變量分配的位置上,此後這兩個變量能夠參與任何操做不會有相互影響。函數

var a = 2;
var b = a; //b是a的值的一個副本  

b++ 
a; //2
b; //3

引用複製: 從一個變量像另外一個變量複製引用類型的值時,一樣將會存儲在變量對象中的值複製一份放到新分配的空間裏中。不一樣的是,這個值的複本其實是一個指針,而這個指針指向存儲在堆中的一個對象。,兩個變量實際上將引用同一個對象,其中改變其中一個變量,就會改變另外一個變量工具

var c = [1,2,3];
var d = c;
d.push(4);
c;  //[1,2,3,4]
d;  //[1,2,3,4]

並且因爲引用指向的是值自己而非變量,因此一個引用沒法更改另外一個引用的指向prototype

var a = [1,2,3]
var b = a;
a; //[1,2,3]
b; //[1,2,3]

b = [4,5,6] //b指向值[4,5,6]
a; //[1,2,3]
b; //[4,5,6]

b = [4,5,6]並不影響a指向值[1,2,3],除非b不是指向數組的引用,而是指向函數a的指針,但在javascript中不存在這樣的狀況
函數傳參: 在javascript中全部函數的參數都是按值傳遞的,也就是說,把函數外部的值複製給函數內部的參數。即在向參數傳遞基本類型的值時,被傳遞的值會被複制給一個局部變量,在向參數傳遞引用類型的值時,會將這個值在內存中的地址複製給一個局部變量。指針

function foo(x){
    x.push(4);
    x; //[1,2,3,4];
    
    x = [4,5,6];
    x.push(7);
    x; //[4,5,6,7]
}
var a = [1,2,3];
foo(a);
a; // 是[1,2,3,4]而不是[4,5,6,7];

咱們在向函數傳參的時候,其實是把引用a的複本賦值給x了,而a仍指向[1,2,3]。code

字符串

字符串和數組很類似,都有length屬性以及indexOf()和concat()方法,在javascript中字符串是不可變的,字符串的成員函數不會改變其原始值,而是建立並返回一個新的字符串。對象

var a = foo;
var b = a.toUpperCase();
a === b //false
a; //"foo";
b; //"FOO"

許多數組函數用來處理字符串很方便,雖然字符串沒有這些函數,但能夠經過借用數組的非變動方法來處理字符串;ip

var a = foo;
a.join; //undefined
a.map;  //undefined

var b = Array.prototype.join.call(a, '-');
var c = Array.prototype.map.call(a, function(v){
    return v.toUpperCase() + ".";
}).join("");

b; //"f-o-o"
c; //"F.O.O"

例如常見的字符串反轉問題

var a = "foo";
var b = Array.prototype.reverse.call(a);
b; //"oof";

//也能夠是
var c = a.split("").resverse().join("");
c; //"oof"

上述方法對於包含複雜字符(Unicode, 星號, 多字節字符等)的字符串不適用,須要特殊的庫來實現

數字

javascript只有一種數值類型: number(數字), 包括整數和帶小數的十進制數,javascript中沒有真正意義上的整數,javascript中的整數就是沒有小數的十進制數,因此42.0等同於整數42。 而數字類型常見的問題就是

0.1 + 0.2 === 0.3 //false

這是由於二進制浮點數中的0.1和0.2並非十分精確,他們相加的結果並不是恰好等於0.3,而是一個比較接近的數字,因此判斷結果爲false。
對於這種狀況,最多見的方法是設置一個偏差範圍值,從ES6開始,該值定義在Number.EPSILON中咱們能夠直接拿來用。

if(!Number.EPSILON){
    Number.EPSILON = Math.pow(2, -52);
}
function foo(n1, n2){
    return Math.abs(n1 - n2) < Number.EPSILON
}
var a = 0.1 + 0.2
var b = 0.3
foo(a, b); //true

特殊的數字

1.不是數字的數字
若是數學運算的操做數不是數字類型(或者沒法解析常規的十進制或十六進制數字),就沒法返回一個有效的數字,這種狀況下返回值爲NaN。例如

var a = 2 / "foo"; //NaN
typeof a === "number"; // true

NaN是一個警惕值,用於指出數字類型中的錯誤狀況,即執行數學運算沒有成功,這是失敗後返回的結果。他是一個特殊值,她和自身不相等

var a = 2 / "foo"
a === NaN; //false

咱們能夠用內建的全局工具函數isNaN(..)來判斷一個值是不是NaN,可是這種方法有嚴重缺陷

var a = 2 / "foo";
var b = foo;
window.isNaN(a); //true;
window.isNaN(b); //true;

對於這種現象,ES6開始使用工具函數Number.isNaN(..)

if(!Number.isNaN){
    Number.isNaN = function(n){
        return n !== n;
    }
}

var a = 2 / "foo";
var b = foo;

Number.isNaN(a); //true
Number.isNaN(b); //false

2.無窮數
在javascript中1 / 0 和 - 1 / 0這種操做會返回Infinity或者-Infinity
javascript使用有限數字表示法,因此javascript的運算結果容易溢出,此時結果爲Infinity或者-Infinity
3.零值
javascript中有一個常規的0,還有一個-0

var a = 0 / -3; // -0
var b = 0 * -3; // -0

-0進行字符串化會返回0

var a = 0 / -3;
a.toString(); //"0";
a + ""; //"0"

將其從字符串轉換成數字,獲得的結果是正確的

+ "-0";  //"0"
Number("-0"); //"0"

布爾

javascript中有兩個關鍵詞true和false,表明真和假,其餘數據類型的值能夠強制轉換爲布爾值。在javascript中假值有這些:
undefined,null,false,+0, -0和NaN,""。除了這些值以外其餘是真值。

相關文章
相關標籤/搜索