JavaScript中数据类型判断

做判断前先来了解下 JavaScript 中的基本数据类型

一、七大数据类型

基本类型:存储在栈( stack )中
1 Number(包括整型和浮点型)
2 String3 Boolean4 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 用来判断类型一点也不靠谱,用来判断实例关系也让人不解
 

 

posted @ 2019-04-17 16:11  青S衫%  阅读(322)  评论(0编辑  收藏  举报