JavaScript的基礎數據類型進階

JavaScript的幾種基礎數據類型進階

JavaScript常見的有五種基本類型:boolean,undefined,null,number,string。ES6新增了symbol。所以從嚴格意義上來說,目前JavaScript有六種數據類型。基本類型的判斷使用typeof操作符,所有基礎類型不可改變。

下面,我們來一探究竟這些數據類型與其轉換規則吧!

  • Boolean類型

Boolean類型在實際的工作中被經常使用,當我們在處理某些JS的業務邏輯時,難免需要通過Boolean值來進行相關的判斷,如if,三目運算等。

與Boolean類型相關的Boolean值轉換方法是Boolean()函數。Boolean()的轉換規則如下

Boolean(true);           // true
Boolean(false);          // false
Boolean(undefined);      // false
Boolean("");             // false
Boolean("  ");           // true
Booleam({});             // true
Booleam([]);             // true
Boolean(NaN);            // false

需要注意的是Boolean函數是if語句的隱式轉換規則(括號內爲非表達式)

var messeage = "    ";
if(messeage) {                           // 這裏if語句進行了隱式轉換,對message調用Boolean方法
    console.log(message);                // "    "
}

在使用邏輯非操作符時,這裏有一個你可能不知道的騷操作:

!!true;           // true
!!false;          // false
!!undefined;      // false
!!"";             // false
!!"  ";           // true
!!{};             // true
!![];             // true
!!NaN;            // false
// 你發現了嗎?

兩個邏輯非操作轉換成Boolean值的結果和Boolean()方法相同。

當然,可以通過new操作符對Boolean函數進行實例化,此時的Boolean爲構造函數,可以傳入一些參數。

  • Undefined類型

undefined表示當前的變量沒有被賦值,它是全局對象的一個變量,不可修改,枚舉,配置

var a;           
typeof a;             // undefined
typeof b;             // undefined,沒有報錯
a === "undefined";    // true,注意:這裏是'==='
b === "undefined";    // Uncaught ReferenceError: b is not defined

通過typeof操作符能判斷一個未聲明或者已聲明未賦值的變量是否是undefined。但是在實際中應該避免未聲明變量的基本類型判斷,因爲它並不適合用於判斷對象的屬性是否存在。

或者細心的你會發現:

// 當JavaScript運行完某個函數時
function test() {
    var a = 100;
    console.log(a);
};
test();
// 打開瀏覽器控制檯,你會看到以下輸出
// 100
// undefined

所以,當函數沒有明確的返回值(return nothing)的時候,它會默認返回一個undefined。

學到了嗎?我們可以通過typeof判斷某個變量是否未定義,或者你可以這樣寫:

var non;
// 常規的判斷方法
if(typeof non === "undefined") { 
    // ... 
};
// 替代typeof的方法
if(non === void 0) { 
    // ... 
};
// 所以你會看到這樣一個神奇的效果
undefined === void 0;      // true !!!

判斷某個變量未定義,可以判斷它是否等於void 0或者void(0),或許你已經在HTML中見識過它的強大了

<a herf="javascript: void(0)">這是一個超鏈接</a>  <!-- 點擊後不幹任何事 -->

void 0代替undefined,可以避免undefined被重寫。

  • Null類型

首先,null不是一個屬性,它是一個值(字面量),它也是一個指針,指向一個空對象的引用。

只有在我們主動將某個變量的值設置爲null時,這個變量才能爲null

var a = null;
a;                 // null

這裏有一個需要注意的問題:

null == undefined;           // true,其實是 == 的隱式轉換規則導致
null === undefined;          // false
  • Number類型

    Number是JavaScrit幾種基本類型中最複雜難理解的類型,它包含的幾種數值轉換方法中總有一些讓人費解的地方,雖然在實際的項目中可能並沒有很大的意義,但還是需要將其理解透徹,以備不時之需,或者說在遇到問題時才能精準定位。

    Number包含兩種數值類型:整數和浮點數(或許在其他強類型語言中,字符串有單雙進度之分,但對於JS來說,它只表示雙精度浮點數,記住了!)

    1. 無窮值Infinity

      在JavaScript中,數值有大小正負之分,所以無窮值也有正無窮+Infinity(Number.POSITIVE_INFINITY)和負無窮-Infinity(Number.POSITIVE_INFINITY),ECMAscript中最小值保存在Number.MIN_VALUE中,如果某個值小於它,那這個值就是-Infinity,對應的最大值爲Numner.MAX_VALUE

      Infinity的計算有些難以讓人理解:

      Infinity + 1;               // Infinity;
      Infinity + Infinity;        // Infinity;
      Infinity - Infinity;        // NaN
      -Infinity + Infinity;       // NaN
      0 / 0;                      // NaN
      

      再看看下面這段取最大值的代碼:

      let arr = [1,5,3,7,2];
      let maxVal = 0;
      arr.forEach(item => {
          if(item > maxVal) maxVal = item;
      })
      console.log(maxVal);                // 7
      // 這段代碼有問題嗎?
      

      如果我們不知道arr數組裏面具體的數據(可能全部爲負值),那麼這段代碼能拿到數組中的最大值嗎?

      答案顯然是拿不到,原因是maxVal = 0導致0始終是最大值,所以maxVal應該初始化爲一個無限小的數值-Infinity

      let maxVal = -Infinity;
      

      這就是Infinity的一個實際應用場景。

      判斷一個數值是否是無窮可以使用isFinite(),ES6新增了Number.isFinite()

    2. 非數值NaN

      NaN是一個數值,通常表示一個計算錯誤時的返回值,看代碼:

      typeof NaN;            // number
      Math.sqrt(-1);         // 嘗試對一個負值求平方根,它將會返回NaN
      

      NaN雖然是一個數值,但是NaN的任何操作都會返回NaN

      NaN/0;                 // NaN
      NaN == NaN;            // false
      NaN === NaN;           // false
      NaN != NaN;            // true
      NaN !== NaN;           // true
      

      判斷一個變量是否是數值可以使用isNaN(),ES6新增了Number.isNaN()

      a) isNaN()

      而在ES6之前,判斷一個值是否是NaN的規則如下:

      判斷參數是否是Number類型,如果是,則返回true;

      如果不是,調用Number()方法,將其轉換爲Number類型;

      然後判斷轉換後的值是否不恆等於(!==)它自己

      // isNaN的實現
      var isNaN = function(value) {
          var nan = Number(value);
          return nan !== nan;                     // 此處運用到了NaN !== NaN
      }
      

      所以,我們可以通過NaN的實現對一些難以理解的結果作出更好的解釋:

      isNaN(NaN);             // true   Numer(NaN) == NaN;    NaN !== NaN;   true
      isNaN('red');           // true   Numer('red') == NaN;  NaN !== NaN;   true
      isNaN(true);            // false  Number(false) == 0;   0 !== 0;       false
      isNaN({});              // true   Number({}) == NaN;    ... ...
      isNaN([]);              // false  Number([]) == 0;      ... ...
      

      isNaN另一個強大的地方在於:可以通過它來確定某個值是否可以參與數學運算

      function isCompute(x) {
          if(isNaN(x)) console.log(x +  ' can not be computed!');
      }
      
      b) Number.isNaN()

      相比於isNaN()Number.isNaN()方法會將傳入的參數轉化成數值再判斷,因爲它更專注於number類型,其判斷條件更爲苛刻。實現如下

      var Number.isNaN = function(x) {
          return typeof x === 'number' && isNaN(x);
      };
      Numer.isNaN(NaN);               // true
      Number.isNaN(true);             // true
      Number.isNaN({});               // true
      Number.isNaN([]);               // true
      // 從直觀的角度來看,[]不能表示爲一個數值。
      

      NumberisNaN()的參數只接受數值,如果要讓它返回true,這個數值必定爲NaN。

    3. 數值轉換

      Number類型的數值轉換有三種:Number()parseInt()parseFloat()

      a) Number()

      Number()函數的轉換規則如下:

      類型
      true 1
      false 0
      null 0
      undefined NaN
      {} NaN
      [] 0
      ‘[]’ NaN
      [2] 2
      [2,1] NaN
      十六進制數 十進制數
      其他非空對象 對象的valueOf() 等於NaN ? 調用toString()
      b) parseInt()

      相比於Number()parseInt()是更爲嚴格的轉換形式,它是通過查找的方式找到數字,直到遇到第一個非空格字符,如果第一個字符不是數字或者負號,就會返回NaN。

      它可以接受第二個參數,表示轉換的進制:當parseInt傳入的第一個參數是字符串時,它會對字符串的每個字符挨個進行數值轉換當傳入的第一個參數不是字符時,它會嘗試將這個參數轉化成十進制的字符串,然後再根據第二個參數對字符串按個轉換

      parseInt('1234a');                 // 1234
      parseInt('10', 8);                 // 8   8進制的10轉換成10進制:1*8^1 + 0*8^0 = 8
      parseInt('0x10', 16);              // 16  16進制的0x10轉化成10進制:12
      parseInt('0x10', 8);               // 0   8進制的0x10轉化成10進制:x是8機制不能解析的字符
      parseInt(0x10, 8);                 /* 14  0x10爲16進制,轉換成10進製爲16,所以相當於                                                 parseInt('16', 8); */
      
      c) parseFloat()

      parseFloat只能解析十進制,他和parseInt大致相同,但是返回的是浮點數,這裏就不再贅述。

  • String類型

    String類型表示由16個Unicode字符組成的元素,將其他類型的值轉換成字符串主要有:toString()String()

    區別:

    toString()是一個屬性方法,調用只能通過點語表示法調用,而且nullundefined沒有這個方法,ES6新增:function.prototype.toString()toString()可以傳入一個參數,表示輸出的進制數;

    String()是一個構造函數,可以將null和undefined轉換成對應的字符串。

    // 可以自己實現一個String方法並設置一些參數
    var String = function(value, hex){
        if(value === 'null') return 'null';
        else if(value === 'undefined') return 'undefined';
        elee return  value.toString(hex);
    }
    
  • Symbol類型

    Symbol類型是ES6新增的基本數據類型,也可以將它成爲atom(原子),它主要是用於設置對象的屬性值,通過Symbol()構造函數可以給對象添加一個匿名屬性(此時的鍵和值都是實例化的Symbol對象,且對象不可枚舉)

    Symbol('a') !== Symbol('a');            // true
    var a = Symbol();
    typeof a ;                              // symbol
    let ob = {};
    obj[a] = ‘a’;
    JSON.stringfy(obj);                     // '{}'
    

    如需查看Symbol更詳細的內容,請點擊MDN Symbol

JavaScript基礎類型基本就這些了,內容如有不準確的地方,歡迎指正。

貴有恆何必三更眠五更起,最無益只怕一日曝十日寒。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章