JavaScript中数据类型判断
做判断前先来了解下 JavaScript 中的基本数据类型
一、七大数据类型
基本类型:存储在栈( stack )中
1 Number(包括整型和浮点型) 2 String、 3 Boolean、 4 Symbol ES6 新增,能作为对象属性的标识符,具有唯一性 5 Undefined、(指变量创建后但没有赋值,变量的默认值是 undefined );规范指定类型为首字母大写Undefined;但是只有一个值,即 undefined (undefined可以被重写 有时候用void 0代替) 6 Null、 空对象指针;规范指定类型为首字母大写NUll;但是只有一个值,即null;null == undefined && null !== undefined
复合类型:值存储在堆( heap )中
1 Object 2 备注:数组( Array )日期( Date )、正则( RegExp )和 函数( Function )都是归属于对象类型 3 但是在使用 typeof 进行判断时候,数组等返回 object,函数作为特殊情况,返回 function(至于为啥返回 function,你得问设计者,也许是为了方便开发者判断呢···)
二、检测方法
数据类型:
1 let a_number = 1 2 let b_string = '1' 3 let c_boolean = true 4 let d_symbol = Symbol('1') 5 let e_undefined = undefined 6 let f_null = null 7 8 let g_object = {} 9 let h_array = [] 10 let i_function = function () {}
2.1 使用typeof 判断 (注意:返回结果全小写)
1 console.log('a_number: ', typeof a_number) // number 2 console.log('b_string: ', typeof b_string) // string 3 console.log('c_boolean: ', typeof c_boolean) // boolean 4 console.log('d_symbol: ', typeof d_symbol) // symbol 5 console.log('e_undefined: ',typeof e_undefined) // undefined 6 console.log('f_null: ', typeof f_null) // object 7 8 console.log('g_object: ', typeof g_object) // object 9 console.log('h_array: ', typeof h_array) // object 10 console.log('i_function: ', typeof i_function) // function
可以看到 typeof 在判断 null、{}、[] 的时候都返回 object,这就需要寻找其他的方法进行区别
2.2 使用 Object.prototype.toString.call
这是一个对象原型扩展函数,用来更精确的区分数据类型
1 console.log('a_number: ', Object.prototype.toString.call(a_number)) // [object Number] 2 console.log('b_string: ', Object.prototype.toString.call(b_string)) // [object String] 3 console.log('c_boolean: ', Object.prototype.toString.call(c_boolean)) // [object Boolean] 4 console.log('d_symbol: ', Object.prototype.toString.call(d_symbol)) // [object Symbol] 5 console.log('e_undefined: ',Object.prototype.toString.call(e_undefined)) // [object Undefined] 6 console.log('f_null: ', Object.prototype.toString.call(f_null)) // [object Null] 7 8 console.log('g_object: ', Object.prototype.toString.call(g_object)) // [object Object] 9 console.log('h_array: ', Object.prototype.toString.call(h_array)) // [object Array] 10 console.log('i_function: ', Object.prototype.toString.call(i_function)) // [object Function]
太长了,封装一下
1 function Type() { 2 let typeFn = {} 3 let typeList = ['Number', 'String', 'Boolean', 'Symbol', 'Undefined', 'Null', 'Object', 'Array', 'Function'] 4 typeList.forEach(type => { 5 typeFn['is' + type] = obj => Object.prototype.toString.call(obj) === '[object ' + type + ']' 6 }) 7 return typeFn 8 } 9 使用: 10 let TypeFn = Type() 11 console.log(TypeFn.isBoolean(false)) // true
三、下面是不靠谱的检测方法
3.1 使用 constructor
1 console.log(a_number.constructor === Number) // true 2 console.log(b_string.constructor === String) // true 3 console.log(c_boolean.constructor === Boolean) // true 4 console.log(d_symbol.constructor === Symbol) // true 5 console.log(e_undefined.constructor === Undefined) // 报错 --- undefined 没有 constructor,也没有 Undefined 对象 6 console.log(f_null.constructor === Null) // 报错 --- null 没有 constructor,也没有 Null 对象 7 console.log(g_object.constructor === Object) // true 8 console.log(h_array.constructor === Array) // true 9 console.log(i_function.constructor === Function) // true
不靠谱要点:
1、undefined 和 null 没有 constructor,不能判断 2、而且在 JavaScript 中,实例化一个构造函数 A 时候,得到的实例对象的 constructor 会指向该构造函数 A,然而该构造函数 A 可能并不是我们所希望的数据类型函数 例如: function A() {} let b = new A() // 此时 b 成为一个对象 b.constructor === A // true b.constructor === Object // false -- 此时使用 constructor 并不能知道 b 是一个对象
3.2 使用 instanceof
根据 MDN 上定义: instanceof 用来测试构造函数的 prototype 是否出现在对象的原型链的任何位置
简单说用来判断 B 是否是 A 的实例,是返回 true ,否则返回 false
instanceof 判断的依据是原型
例子: 正常情况: 构造函数: function A() {} 对象: let B = new A() 结果: B instanceof A // true 伪造情况: 构造函数: function A() {} 对象: let B = {} B.__proto__ = A.prototype 如果: A.prototype === B.__proto__ 则 console.log(B instanceof A) // true
就算 A 和 B 没有任何关系, 通过 A.prototype === B.__proto__ 关联,就能误导 instanceof 的判断
而且 根据 instanceof 的判断依据
[] instanceof Array // true [] instanceof Object // true 因为原型链的最后都存在 Object.prototype
无法准确判断 [] 的类型
加上还有令人不解的现象:
神奇之处:
'1'.__proto__ === String.prototype
但是
'1' instanceof String 却返回 false
正常情况: new String(1).__proto__ === String.prototype
new String(1) instanceof String // 返回 true
神奇之处:
(1).__proto__ === Number.prototype
但是
1 instanceof Number 却返回false
正常情况: new Number(1).__proto__ === String.prototype
new Number(1) instanceof Number // 返回 true
所以 instanceof 用来判断类型一点也不靠谱,用来判断实例关系也让人不解
都读到最后了、留下个建议如何