1. 程式人生 > >js資料型別及檢測方法

js資料型別及檢測方法

###一、資料型別檢測方法 在js中,有四種用於檢測資料型別的方式,分別是:

typeof  用來檢測資料型別的運算子 instanceof    檢測一個例項是否屬於某個類 constructor   建構函式 Object.prototype.toString.call()  原型鏈上的Object物件的toString方法 下面我們就來分別介紹一下上面四種方法的適用場景和侷限性。

####1.typeof 用來檢測資料型別的運算子 使用typeof檢測資料型別,返回值是字串格式。能夠返回的資料型別有6種

是:“number”,“string”,“bolean”,“undefined”,“function”,“object”。

<script>
  console.log(typeof(1));  //number
  console.log(typeof('hello'));  //string
  console.log(typeof(true));  //boolean
  console.log(typeof(undefined));  //undefined
  console.log(typeof(null));  //object
  console.log(typeof({}));  //object
  console.log(typeof(function() {}));  //function
</script>

侷限性:

typeof (null); //“object”。這是由於在js中,null值表示一個空物件指標,而這也正是使用typeof操作 符檢測null值時會返回"object"的原因(筆試面試常考) 不能具體的細分是陣列還是正則,還是物件中其他的值,因為使用typeof檢測資料型別,對於物件資料型別的所有的值,最後返回的都是"object" ####2.instanceof 檢測某一個例項是否屬於某個類 instanceof主要用來彌補typeof不能檢測具體屬於哪個物件的侷限性。

<script>
  let arr = [1,2,3];
  let reg = /\w/;
  console.log(arr instanceof Array);  //true
  console.log(arr instanceof Object);  //true
  console.log(reg instanceof RegExp);  //true
  console.log(reg instanceof Object);  //true
</script>

侷限性:

不能用於檢測和處理字面量方式創建出來的基本資料型別值,即原始資料型別 instanceof的特性:只要在當前例項的原型鏈上的物件,我們用其檢測出來都為true 在類的原型繼承中,我們最後檢測出來的結果未必正確 ####3.constructor 建構函式 是函式原型上的屬性,該屬性指向的是建構函式本身。

作用和instsnceof非常相似,與instanceof不同的是,不僅可以處理引用資料型別,還可以處理原始資料型別。

<script>
  let num = 12;
  let obj = {};
  console.log(num.constructor == Number);//true
  console.log(obj.constructor == Object);//true
</script>

但是要注意一點的是,當直接用(物件字面量或原始資料).constructor時,最好加上()。為了便於理解,我們來看一個例子。

<script>
  1.constructor === Number;    //報錯,Invalid or unexceped token
  (1).constructor === Number;    //true
  {}.constructor === Number;    //報錯,Invalid or unexceped token
  ({}).constructor === Number;  //true
</script>

這主要是由於js內部解析方式造成的,js會把1.constructor解析成小數,這顯然是不合理的,小數點後應該是數字,因此就會引發報錯。js會把{}解析成語句塊來執行,這時後面出現一個小數點顯然也是不合理的,因此也會報錯。為了解決這個問題,我們可以為表示式加上()使js能夠正確解析。

侷限性:我們可以把類的原型進行重寫,在重寫的過程中很可能把之前constructor給覆蓋了,這樣檢測出來的結果就是不準確的

<script>
   function Fn() {};
  Fn.prototype = new Array;
  var f = new Fn;
  //f是一個函式,按道理說他的建構函式應該是Function,但是修改其原型鏈後,它的constructor變成了Array.
  console.log(f.constructor == Array);  //true
</script>

####4.Object.prototype.toString.call() 原型鏈上的Object物件的toString方法 Object.prototype.toString的作用是返回當前方法的執行主體(方法中的this)所屬類的詳細資訊,是最全面也是最常用的檢測資料型別的方式。

返回值的型別為string型別。

<script> 
  console.log(Object.prototype.toString.call(1));          //[object Number]
  console.log(Object.prototype.toString.call(/^sf/));        //[object RegExp]
  console.log(Object.prototype.toString.call("hello"));      //[object String]
  console.log(Object.prototype.toString.call(true));        //[object Boolean]
  console.log(Object.prototype.toString.call(null));        //[object Null]
  console.log(Object.prototype.toString.call(undefined));      //[object Undefined]
  console.log(Object.prototype.toString.call(function() {}));    //[object Function]
  console.log(typeof(Object.prototype.toString.call(function() {})));    //string
</script>

####二、資料型別

棧 :棧,只允許在一段進行插入或者刪除操作的線性表,是一種先進後出的資料結構。 堆 :堆是基於雜湊演算法的資料結構。 佇列:佇列是一種先進先出(FIFO)的資料結構。 JavaScript中將資料型別分為基本資料型別和引用資料型別,它們其中有一個區別就是儲存的位置不同。 a.我們都知道JavaScript中的基本資料型別有:

String
Number
Boolean
Undefined
Null
Symbol(暫時不管)

基本資料型別都是一些簡單的資料段,它們是儲存在棧記憶體中。 b.JavaScript中的引用資料型別有:

Array
Object

引用資料型別是儲存在堆記憶體中的,然後再棧記憶體中儲存一個對堆記憶體中實際物件的引用。所以,JavaScript中對引用資料型別的操作都是操作物件的引用而不是實際的物件。

可以理解為,棧記憶體中儲存了一個地址,這個地址和堆記憶體中的實際值是相關的。 c.圖解 (可以通過下圖來表示資料型別在記憶體中的儲存情況):

var name="axuebin";
var age=25;
var job;
var arr=[1,2,3];
var obj={age:25};

image.png 此時name,age,job三種基本資料型別是直接存在棧記憶體中的,而arr,obj在棧記憶體中只是存了一個地址來表示對堆記憶體中的引用。 d.複製

基本資料型別

對於基本資料型別,如果進行復制,系統會自動為新的變數在棧記憶體中分配一個新值,很容易理解。

引用資料型別

如果對於陣列、物件這樣的引用資料型別而言,複製的時候就會有所區別了:

系統也會自動為新的變數在棧記憶體中分配一個值,但這個值僅僅是一個地址。也就是說,複製出來的變數和原有的變數具有相同的地址值,指向堆記憶體中的同一個物件。 image.png

當我修改obj或objCopy時,都會引起另一個變數的改變。 參考文章https://m.jb51.net/article/145078.htm https://m.jb51.net/article/135920.htm