歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

JavaScript進階:數據類型

一、六種數據類型 (弱類型數據)

1.基本數據類型(5種):Undefined、Null、Boolean、Number、String

2.引用數據類型(1種):Object  例如: Function Date Array ...

在js中定義變量的時候無需指定類型。比如定義一個變量 var num = 16, 而此時我們也可以把一個字符串賦值給這個變量 num = "this is a string",這樣也是合法的。那可能有的朋友覺得js好簡單,定義變量的時候連類型是什麼都不用管,是這樣的嗎?那下面我們來看一下:

  (1).  16 + 16 的運算結果是什麼呢,這個很簡單是 32

  (2). 我們把第一個 16 用雙引號引起來,理解為字符串。 "16" + 16 的運算結果是什麼呢,還是 32 嗎?肯定不是啦,此時這裡的理解為字符串拼接,答案為 “1616” 這樣一個字符串。

  (3). 我們繼續看同樣是那如果同樣是字符串或者是數字,我們把 + 變成 -,"16" - 16 此時運算結果是什麼呢? 答案是 0。這裡的理解為數字的運算所以答案就是0。

  小結:js在定義一個變量的時候雖然不用指定變量的數據類型,但是在涉及到操作符等等的一些運算的時候,背後往往有很多的隱式轉換邏輯。

 

二、隱式轉換 (+ 和 -,== 和 ===)

1.借著上面提到的我們舉一個例子:

   "16" + 6  // "166"  (字符串拼接)

   "16" - 6  // 10 (數字運算)

  我們往往可以利用(+/-)規則來進行轉換類型。

  比如:我們想把變量num 轉換成數字類型,一個非常簡單的方法我們就可以 num - 0。又或者我們想把num轉換成 String 類型,我們該怎麼辦呢,對就是加一個空的字符串 num + ""。

2. == 和 ===

  (一)、相等運算符 (==)

    1、如果一個值是null,另一個是undefined,則它們相等。

    2、如果一個值是數字,另一個是字符串,先將字符串轉換為數字,然後使用轉換後的值比較。

    3、如果其中一個值是true,則將其轉換為1再進行比較。如果其中一個值是false,則將基轉換為0再進行比較。

    4、如果一個值是對象,另一個值是數字或字符串,則將對象轉換為原始值,然後再進行比較。對象通過toString()方法或valueOf()方法轉換為原始值。JavaScript核心的內置類首先嘗試使用valueOf(),再嘗試使用toString(),除了日期類,日期類只使用toString()轉換。那些不是JavaScript語言核心中的對象則通過各自的實現中定義的方法轉換為原始值。

    5、其他不同類型之間的比較均不相等.

    例如: null == undefined, //true

        “16” == 16,  //true

          0 == false, //true

        [1,2] == [1,2],  //false

        new Object() == new Object(),  //false

          new Object().toString() == new Object().toString(),   //true

        new String("aaa") == "aaa",  //true

        new String("11") == 11,  //true 

  (二)、嚴格等於(===)

    1、首先判斷他們的類型,如果兩個值類型不相同,則它們不相等,直接返回 false。   

      // “16” === 16,  //false

    2、如果兩個值都是null或者都是undefined,則它們才相等。

       //  null === null, //true,   undefined=== undefined, //true    undefined === null  //false

    3、如果兩個值都是布爾值true或false,則它們相等。

    4、如果其中一個值是NaN,或者兩個兩個值都是NaN,則它們不相等。NaN和其他任何值都是不相等的,包括它本身!!!通過x!==x來判斷x是否為NaN,只有在x為NaN的時候,這個表達式的值才為true。

    5、如果兩個值為數字,且數值相等,則它們相等。如果一個為0,另一個為-0,則它們同樣相等。

    6、如果兩個值為字符串,且所含的對應位上的16位數完全相等,則它們相等。如果它們的長度或內容不同,則它們不等。兩個字符串可能含義完全一樣且所顯示出手字符也一樣,但具有不同編碼的16位值。JavaScript並不對Unicode進行標准化的轉換,因此像這樣的字符串通過"==="和"=="運算符的比較結果也不相等。

    7、如果兩個引用值同一個對象、數組或函數,則它們是相等的。如果指向不同的對象,則它們是不等的。盡管兩個對象具有完全一樣的屬性。

 

三、包裝對象

      定義:在JavaScript中,“一切皆對象”,數組和函數本質上都是對象,就連三種原始類型的值——數值、字符串、布爾值——在一定條件下,也會自動轉為對象,也就是原始類型的“包裝對象”。

通俗來講:字符串,數值,字符串,這些單身狗看其它人都有對象,非常不爽,所以自己也搞了個對象,名字叫包裝。

1.一般來說,只有對象是可以對屬性進行讀寫操作的。但是聰明的騷年,你有沒有發現,平時我們用得很多的字符串方法和屬性,都是直接通過”.”操作符訪問的。比如:

  console.log("hello world".length);
  console.log("this a string".indexOf("a"));

2.其實,在我們調用這些方法和屬性時,JS內部已經隱式地幫我們幫創建了一個包裝對象了,以上的實際的情形應該是這樣的:

  console.log(new String("hello world").length);
  console.log(new String("this a string").indexOf("a"));

3.但是兩者還是有區別的,
  區別1:
  浏覽器自己隱式創建的包裝對象和你顯式創建的包裝對象不嚴格相等。簡單來說,雖然說表面JS對親生的與領養的一樣,但實際上,親生的不等於領養的。

    var a1 = "test",
        a2=new String("test");
    console.log(a1 == a2);//true
    console.log(a1 === a2);//false

  區別2:
  隱式創建的包裝對象,在使用完後之後就會被拋棄了。簡單來說就是,一個大大的負心漢,上完我,就拋棄,還重新去找其他對象。
  拿我們開頭的那道題來說:
    test.a = "hello";
  這裡隱式創建了一個包裝對象,所以這裡賦值不會報錯。
    console.log(test.a);
  這裡之前的包裝對象已經被拋棄了,但是使用了"."運算符,所以又創建一個新的包裝對象,但是這個對象的屬性a並沒有賦值,所以屬性a的值是undefined。

  說到實際運用中,有的浏覽器性能不是很好,比如說低版本IE,當頻繁處理字符串時,效率會很低。所以很多時候,我們還不如直接顯式地創建包裝對象,防止浏覽器過多地創建隱式的包  裝對象,提升性能。

    //不推薦使用種方法
    var example = "this is a example";  
    //推薦使用這種方法,提升性能。
    var example2 = new String("this is a example");

四、類型檢測

  在js中檢測類型的方法有很多,比如 typeof、instanceof、Object.prototype.toString、constructor、duck type

  1. typeof 運算符,有兩種方式 typeof + 檢測目標 或者 typeof (檢測目標),該方法適用於基本數據類型和函數的檢測(遇到null失效),返回的結果都是字符串

    typeof 100   “number”

    typeof true   “boolean”

    typeof("hello")  "String"

    typeof Function   “Function”

    typeof undefined  “undefined”

    typeof null  “Object”  歷史遺留的問題,為了兼容

    typeof NaN  “number”   判斷NaN的方法可以用isNaN(NaN)來判斷,如果返回true就是NaN

    typeof new Object()   “Object”

    typeof [1,2]   "Object"

    大家可能注意到了,typeof在檢測對象類型的時候是無法區分的,此時我們就要用第二種方法instanceof

  2.instanceof運算符(適用於自定義對象或者原生對象數據類型的檢測),基於原型鏈的類型檢測

    比如判斷一個對象是不是數組: [1,2] instanceof Array 返回 true

    obj instanceof Object   :它期望左操作數obj 是一個對象,如果是一個數字1,2,3或者true,false時就會直接返回false。

                 它期望右操作數是一個函數對象或者是函數構造器,如果不是就會拋出Typeerror異常

    instanceof 工作的一個大概的原理就是它會判斷左操作數這樣一個對象的原型鏈上是否有右邊這個構造函數的prototype屬性

    我們舉一個例子:

      function Person(){}

      function Student(){}

      Student.prototype = new Person();

      Student.protype.constructor = Student

      var a = new Person();

      var b = new Student();

      -----------------------------------------

      a instanceof Person   // true

      b instanceof Student   //true

      a instanceof Student   //false

      b instanceof Person   //true

    注意:不同window之間和跨iframe之間是不可以使用instanceof的,雖然看著是同一個對象但是在不同window之間和跨iframe之間是不同的對象,每個iframe下都有自己���一套原型鏈,跨frame實例化的對象彼此是不共享原型鏈,因此會返回false

  3.Object.prototype.toString 函數方法

    Object.prototype.toString.call()或者Object.prototype.toString.apply()

    例如:

    Object.prototype.toString.call([])     //"[object Array]"

    Object.prototype.toString.call(function(){})  //"[object Function]"

    Object.prototype.toString.call(undefined)  //"[object Undefined]"

    Object.prototype.toString.call(null)      //"[object Null]"

 

    注意:1.解決了跨iframe 失效的問題

       2.IE 6,7,8下  Object.prototype.toString.call(null或undefined)      //"[object Object]"

  4.constructor方法

    function A(){}; 

    function B(){}; 

    A.prototype = new B(); 

    var aObj = new A(); 

    --------------------------------

    aObj.constructor === B; //true; 

    aObj.constructor === A; //false;

        注意:類繼承時會出現問題

  5.duck type(鴨子類型)

    比如檢測數組時,我們可以檢測他有沒有push()方法等等

Copyright © Linux教程網 All Rights Reserved