js中基本數據類型有6種number、string、undefined、null、boolean,Symbol (ES6 新增,表示獨一無二的值),還有一種數據類型為引用數據類型統稱為Object對象,其中包括常見的Arry(數組)、Function(函數)、Date等,
基本數據類型
1、值是不可變的
var a='apple'; var b=a.toUpperCase(); console.log(a) //apple console.log(b) //APPLE
2、基本數據類型直接存放在棧中,占據空間、大小固定,屬於被頻繁使用的,所以放入棧中存儲。
引用數據類型
1、值是可以變的
var a={ name:"yuan", sex:"man" }; a.name='zhi'; console.log(a) //{name: "zhi", sex: "man"}
2、同時保存在棧和堆中
引用數據類型數據一般比較大、結構比較復雜,如果存儲在棧中會影響到程序的性能,所以分為兩部分指針和實體,指針類似地址名片記錄着數據存放的實際位置,存放於棧中,實體就是數據的實際起始地址。存放在堆中,使用的時候解釋器獲得指針地址后去堆中找到相對應的數據。
因為這種結構,所以引用數據類型的直接賦值是指針的賦值,指向的都是同一個實體對象,所以通過某一個指針修改,存放於堆中的實體對象都會發生改變。
var a={ name:"yuan", sex:"man" }; var b=a; b.name='zhi'; console.log(a) //{name: "zhi", sex: "man"} console.log(b) //{name: "zhi", sex: "man"}
數據類型的判斷(原生js)
1、typeof
這是最基本的一個判斷方式,該操作符返回一個表示數據類型的字符串,共有7種結果:number、string、boolean、object、function、undefined、symbol。很明顯它不能區分引用數據類型里面的數組等對象(包括null);
var a=[1,2,3]; var b=null; console.log(typeof a) //object console.log(typeof b) //object
2、instanceof
instanceof是用來判斷A是否為B的實例,表達式:A instanceof B;如果A是B的實例則返回true,否則返回false;instanceof運算符是通過判斷該對象在原型鏈上是否存在一個構造函數的prototype屬性;
var a=[1,2,3]; var b=new Date(); console.log(a instanceof Array) //true console.log(b instanceof Date) //true
依上面所說這將主要涉及js中非常重要的原型鏈繼承機制,這里就不詳細說了,簡單來說在 JavaScript 原型繼承結構里面,規范中用 [[Prototype]] 表示對象隱式的原型,在 JavaScript 中用 __proto__ 表示,並且在 Firefox 和 Chrome 瀏覽器中是可以訪問得到這個屬性的,但是 IE 下不行。所有 JavaScript 對象都有 __proto__ 屬性,但只有 Object.prototype.__proto__ 為 null,前提是沒有在 Firefox 或者 Chrome 下修改過這個屬性。這個屬性指向它的原型對象。 至於顯示的原型,在 JavaScript 里用 prototype 屬性表示,這個是 JavaScript 原型繼承的基礎知識。
根據相關規范和網上例子寫一個instanceof:
function instance_of(L, R) {//L 表示左表達式,R 表示右表達式 var O = R.prototype;// 取 R 的顯示原型 L = L.__proto__;// 取 L 的隱式原型 while (true) { if (L === null) return false; if (O === L)// 這里重點:當 O 嚴格等於 L 時,返回 true return true; L = L.__proto__; } } var a=[1,2,3]; var b=new Date(); console.log(instance_of(a,Array)) //true console.log(instance_of(b,Date)) //true
instanceof也具有以下三點的不足:
1、不能檢測null和undefined
console.log(instance_of(null instanceof null)) console.log(instance_of(undefined instanceof undefined))
對於特殊的數據類型 null 和 undefined,他們的所屬類是 Null 和 Undefined,但是瀏覽器把這兩個類保護起來了,不允許我們在外面訪問使用。
2、通過構造函數實例化和字面量生成的基本類型判斷是有一定區別的
var a=123; var b=new Number(123) console.log(a instanceof Number) //false console.log(b instanceof Number) //true
為什么會這樣呢?嚴格意義上講只有實例創建出來的數據才是標准的對象數據類型值,也是標准的 Number 這個類的一個實例;對於字面量方式創建出來的結果是基本的數據類型值,不是嚴謹的實例,但是由於 JS 的松散特點,導致了可以使用 Number.prototype 上提供的方法。
3、constructor
constructor和prototype 非常相似,但 constructor 檢測 Object 與 instanceof 不一樣,還可以處理基本數據類型的檢測。
var a=123; var b=new Number(123) console.log(a.constructor==Number) //true console.log(b.constructor==Number) //true
constructor具有以下兩點不足
1、null 和 undefined 是無效的對象,因此是不會有 constructor 存在的,這兩種類型的數據需要通過其他方式來判斷。
2、函數的 constructor 是不穩定的,這個主要體現在把對象的原型進行重寫,在重寫的過程中很有可能出現把之前的 constructor 給覆蓋了,這樣檢測出來的結果就是不准確的。
function Fn() { } Fn.prototype=new Array(); var a=new Fn(); console.log(a.constructor==Array) //true
4、Object.prototype.toString.call()
這個是最准確最常用的方式,首先獲取Object上面的toString方法,方法執行時讓里面的this指向第一個參數的值。
關於toString:
-
本意是轉換為字符串,但是某些 toString 方法不僅僅是轉換為字符串對於 Number、String,Boolean,Array,RegExp、Date、Function 原型上的 toString 方法都是把當前的數據類型轉換為字符串的類型(它們的作用僅僅是用來轉換為字符串的)
- 對於 Number、String,Boolean,Array,RegExp、Date、Function 原型上的 toString 方法都是把當前的數據類型轉換為字符串的類型(它們的作用僅僅是用來轉換為字符串的)
- Object 上的 toString 並不是用來轉換為字符串的
Object 上的 toString 它的作用是返回當前方法執行的主體(方法中的 this)所屬類的詳細信息即"[object Object]",其中第一個 object 代表當前實例是對象數據類型的(這個是固定死的),第二個 Object 代表的是 this 所屬的類是 Object。
console.log(Object.prototype.toString.call(123)) //[object Number] console.log(Object.prototype.toString.call(null)) //[object Null] console.log(Object.prototype.toString.call({})) //[object Object] console.log(Object.prototype.toString.call(undefined)) //[object Undefined] console.log(Object.prototype.toString.call('123')) //[object String]