在 JavaScript 里使用 typeof 来判断数据类型,只能区分基本类型,即 "number","string","undefined","boolean","object","function","symbol" (ES6新增)七种。
对于 数组、null、对象,使用 typeof 都会统一返回 "object" 字符串。
要想区别 对象、数组、函数 单纯使用 typeof 是不行的,JavaScript中,通过Object.prototype.toString方法,判断某个对象值属于哪种内置类型。
Object.prototype中的toString方法被数组Array继承下来了,作为 儿子的数组 重写了toString方法,所以直接调用数组对象上面的toString方法调用到的实际是重写后的方法,并不是Object.prototype中的toString方法。
重写后的toString方法可以把对象转换成字符串,还可以把数值转换成不同进制的数。
[1,2].toString();// "1,2" 得到字符串 (10).toString(2);//10进制转2进制 1010 ,如果1.toString(2)会报错,因为js会认为.是数字的小数点而不是调用符号这里面就涉及到js原型及原型链的相关知识。
var arr=[1,2,3]; Object.prototype.toString.call(arr); Array.prototype.toString.call(arr);所以,只有Object.prototype上的toString才能用来进行复杂数据类型的判断。
js中的对象都继承自Object,所以当我们在某个对象上调用一个方法时,会先在该对象上进行查找,如果没找到则会进入对象的原型(也就是.prototype)进行查找,如果没找到,同样的也会进入 对象原型的原型 进行查找,直到找到或者进入原型链的顶端Object.prototype才会停止。
所以,当我们使用arr.toString()时,不能进行复杂数据类型的判断,因为它调用的是Array.prototype.toString,虽然Array也继承自Object,但js在Array.prototype上重写了toString,而我们通过toString.call(arr)实际上是通过原型链调用了Object.prototype.toString。
对常用值类型应用 Object.prototype.toString.call() 方法结果如下:
Object.prototype.toString.call(123) //[object Number] Object.prototype.toString.call('123') //[object String] Object.prototype.toString.call(undefined) //[object Undefined] Object.prototype.toString.call(true) //[object Boolean] Object.prototype.toString.call({}) //[object Object] Object.prototype.toString.call([]) //[object Array] Object.prototype.toString.call(function(){}) //[object Function] Object.prototype.toString.call(null) //[[object Null]]实际应用:
function deepClone(data) { const type = this.judgeType(data); let obj = null; if (type == 'array') { obj = []; for (let i = 0; i < data.length; i++) { obj.push(this.deepClone(data[i])); } } else if (type == 'object') { obj = {}; for (const key in data) { if (data.hasOwnProperty(key)) { obj[key] = this.deepClone(data[key]); } } } else { return data; } return obj; } function judgeType(data) { const toString = Object.prototype.toString; const map = { '[object Boolean]': 'boolean', '[object Number]': 'number', '[object String]': 'string', '[object Function]': 'function', '[object Array]': 'array', '[object Date]': 'date', '[object RegExp]': 'regExp', '[object Undefined]': 'undefined', '[object Null]': 'null', '[object Object]': 'object' } const type = map[toString.call(data)]; return type; } let test = { a: 'happy chen', hobby: ['跑步', '看书', '五子棋'], foods: { fruit: ['雪莲果', '柚子', '香蕉'] } } console.log(deepClone(test)); test.foods.fruit[0] = '南果梨'; console.log(test);