一 JavaScript数据类型
基本类型
- Number
- String
- Boolean
- undefined
- null
- Object
- Bigint
- Symbol 引用类型 Function, Object ,Array
二 如何判断JavaScript的数据类型
JavaScript是一门动态类型的语音,一个变量从声明到最后使用,中间经理了很多函数对象,最终的数据类型也会发生变化,所以掌握判断数据类型的方法就显得尤为重要。
第一种的方法 typeof
typeof undefined //"undefined"
typeof null // "object"
typeof 1 // "number"
typeof "1" // "string"
typeof Symbol() // "symbol"
typeof function() {} // "function"
typeof {} // "object"
typeof Number(1) // "number"
typeof String("1") // "string"
typeof new Number(1) // "object" typeof new String(1) // "object"
注意点1:typeof 不能识别null 如何识别null
可以直接使用===运算符来判断或者使用Object.prototype.toString
注意点2:typeof作用于未定义的变量会报错吗
不会报错会返回undefined
注意点3:typeof Number(1)和typeof String("a") 会返回什么
会返回number和string,
原因:因为Number和String作为普通函数调用的时候,
是吧参数转化为相应的原始数据类型,也就类似于做一个
强制类型转化的操作而不是默认当做构造函数
从上面看出对于返回值是object的,有三情况
- 1:null
- 2:object
- 3:array
所以可以发现typeof可以判断基本数据类型,但是难以判断除了函数以外的复杂类型
第二种的方法 instanceof
3 instanceof Number // false
'3' instanceof String // false
true instanceof Boolean // fals
instanceof 可以用来判断对象的类型:
var date = new Date()
date instanceof Date // true
var number = new Number()
number instanceof Number // true
var string = new String()
string instanceof String // true
const obj = {}
const arr = []
obj instanceof Object // true
arr instanceof Object // true
arr instanceof Array // true
instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,所以instanceof是通过原型链来判断的,但是对于对象来说,Array也会被转换成Object,所以是没办法区分字符串类型和字符串对象类型,布尔类型和布尔对象类型,数字类型和数字对象类型,同时instanceof 的结果并不一定是可靠的,因为在 ECMAScript7 规范中可以通 过自定义 Symbol.hasInstance 方法来覆盖默认行为。
第三种方法 Object.prototype.toString.call()
对于 Object.prototype.toString() 方法,会返回一个形如 "[object XXX]" 的字符串。
如果对象的 toString() 方法未被重写,就会返回如下面形式的字符串。但是,大多数对象,toString() 方法都是重写了的,这时,需要用 call() 或 Reflect.apply() 等方法来调用。
对于 Object.prototype.toString.call(arg),若参数为 null 或 undefined,直接返回结果。
Object.prototype.toString.call(null); // => "[object Null]"
Object.prototype.toString.call(undefined); // => "[object Undefined]"
若参数不为 null 或 undefined,则将参数转为对象,再作判断。
对于原始类型,转为对象的方法即装箱。转为对象后,取得该对象的 [Symbol.toStringTag] 属性值(可能会遍历原型链)作为 tag,如无该属性,或该属性值不为字符串类型,则依下表取得 tag, 然后返回 "[object " + tag + "]" 形式的字符串。
// Boolean 类型,tag 为 "Boolean"
Object.prototype.toString.call(true); // => "[object Boolean]"
// Number 类型,tag 为 "Number"
Object.prototype.toString.call(1); // => "[object Boolean]"
// String 类型,tag 为 "String"
Object.prototype.toString.call(""); // => "[object String]"
// Array 类型,tag 为 "String"
Object.prototype.toString.call([]); // => "[object Array]"
// Arguments 类型,tag 为 "Arguments"
Object.prototype.toString.call((function() {
return arguments;
})()); // => "[object Arguments]"
// Function 类型, tag 为 "Function"
Object.prototype.toString.call(function(){}); // => "[object Function]"
// Error 类型(包含子类型),tag 为 "Error"
Object.prototype.toString.call(new Error()); // => "[object Error]"
// RegExp 类型,tag 为 "RegExp"
Object.prototype.toString.call(/\d+/); // => "[object RegExp]"
// Date 类型,tag 为 "Date"
Object.prototype.toString.call(new Date()); // => "[object Date]"
// 其他类型,tag 为 "Object"
Object.prototype.toString.call(new class {}); // => "[object Object]"
下面为部署了 Symbol.toStringTag 的例子。可以看出,属性值期望是一个字符串,否则会被忽略。
var o1 = { [Symbol.toStringTag]: "A" };
var o2 = { [Symbol.toStringTag]: null };
Object.prototype.toString.call(o1); // => "[object A]"
Object.prototype.toString.call(o2); // => "[object Object]"
Symbol.toStringTag 也可以部署在原型链上:
class A {}
A.prototype[Symbol.toStringTag] = "A";
Object.prototype.toString.call(new A()); // => "[object A]"
总结:
-
基本数据类型可以用 typeof 来判断,要注意的是
typeof null为 "object" 的情况。 -
instanceof 只能用来判断引用数据类型,基本数据类型不可以。缺点是原型链指向改动的话,这个的判断就可能会出错。
-
Object.prototype.toString 适合判断任意类型数据。