JavaScript中判断数据类型,浅拷贝和深拷贝详解

一.JS中的数据类型

JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Symbol、BigInt、Object。

其中分为:

  • 基本数据类型:Number,String,Boolean,Undefined,Null,Symbol,bigint
  • 引用数据类型:Object,Array,Map,Set,Function,Date,Error

二.JS中判断数据类型

1.typeof 

  • 基本数据类型:除了null之外都可以正确判断

       - number,string,boolean,undefined,symbol,bigint-判断正确

       - null-判断错误

  • 引用数据类型:除了function之外都会判断为object

       - null,object,array,map,set,date,error这几种类型都会判断为object

       - function可以正确判断

// 基本数据类型 除了null不能正确检测之外,其余的都可以正确检测
console.log(typeof 5) //number
console.log(typeof '哈哈')  // string
console.log(typeof true) // boolean
console.log(typeof undefined) // undefined
console.log(typeof Symbol()) // symbol
console.log(typeof 5n) // bigint
console.log(typeof null) // object

//引用数据类型
console.log(typeof {name:'张三'}) // object
console.log(typeof [1,2,3,4]) // object
console.log(typeof new Map()) // object
console.log(typeof new Set()) // object
console.log(typeof new Date()) // object
console.log(typeof new Error()) // object
console.log(typeof function(){}) // function

2.instanceof

        instanceof 运算符可以用来构造函数的 prototype 是否出现在一个对象的原型链中

//   可以正确检测引用数据类型
console.log({name:'张三'} instanceof Object) // true
console.log( [1,2,3,4] instanceof Array) // true
console.log( new Map() instanceof Map) // true
console.log( new Set() instanceof Set) // true
console.log( new Date() instanceof Date) // true
console.log( new Error() instanceof Error) // true
console.log( function(){} instanceof Function) // true

// 基本数据类型不是对象,不存在原型链,不能正确判断
console.log( 5 instanceof Number) //false
console.log( '哈哈' instanceof String)  // false
console.log( true instanceof Boolean) // false
console.log( Symbol() instanceof Symbol) // false
console.log( 5n instanceof BigInt) // false
console.log( null instanceof Object) // false
console.log( undefined instanceof Object) // false
// console.log( null instanceof null) // null不是构造函数 不能这样判断
// console.log( undefined instanceof undefined) // undefined不是构造函数 不能这样判断

// 基本数据类型对应的包装类型
// 通过new操作符创建出来
console.log( new Number(5) instanceof Number) //true
console.log( new String('哈哈') instanceof String)  // true
console.log( new Boolean(false) instanceof Boolean) // true
console.log( new Number(5) instanceof Object) //true
console.log( new String('哈哈') instanceof Object)  // true
console.log( new Boolean(false) instanceof Object) // true
// console.log( new Symbol() instanceof Symbol) // Symbol is not a constructor
// console.log( new BigInt(5) instanceof BigInt) // BigInt is not a constructor
  • 引用数据类型全部可以正确检测
  • 基本数据类型不是用new声明的不存在原型链,无法正确检测
  • 基本数据类型number,string,boolean的包装类型,使用new操作符创建,可以正确的检测类型,可以正确检测类型,它还可以检测出多层继承关系
  • null、undefined、symbol和bigint,不存在构造函数,不存在包装类型,不能通过instanceof检测类型

3.constructor

        通过直接访问对象的构造函数来判断变量的类型,对于有构造函数的变量来说,可以正确判断类型,如果事先修改了对象的原型,constructor 就不能用来判断数据类型了。对了null和unfefined来说,没有构造函数,无法通过这种方式判断类型。

// 当基本数据类型调用方法的时候,js引擎会自动将数据转换成对于的包装类型
// 有构造函数的数据可以通过constructor正确判断类型
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(3n.constructor === BigInt); // true
console.log(Symbol().constructor===Symbol); // true
// 这里有一点特殊的是 symbol类型的值无法通过new操作符创建,通过Symbol()函数创建
// console.log(new Symbol()); // Symbol is not a constructor

console.log((function() {}).constructor === Function); // true
console.log({}.constructor === Object); // true
console.log([].constructor === Array); // true
console.log(new Map().constructor === Map); // true
console.log(new Set().constructor === Set); // true
console.log(new Date().constructor === Date); // true
console.log(new Error().constructor === Error); // true

// 没有构造函数的数据无法通过constructor判断类型
// console.log(null.constructor); // Cannot read properties of null (reading 'constructor')
// console.log(undefined.constructor); // Cannot read properties of undefined (reading 'constructor')
  • 当基本数据类型调用方法或者属性的时候,js引擎会自动将数据转换成对应的包装类型,因此,基本数据类型也可以通过constructor获取构造函数
  • 还有一点需要注意,symbol类型的值无法通过new操作符创建,通过Symbol()函数创建,其构造函数指向Symbol()

3.Object.prototype.toString

        在任何值上调用 Object 原生的 toString() 方法,都会返回一个 [object NativeConstructorName] 格式的字符串。每个类在内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。

所有类型的变量都可以通过这种方式正确检测类型。

为什么通过Object.prototype.toString.call()的方式?

        这是因为toString是Object的原型方法,而Array、function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object原型上的toString方法。

// 所有类型都可以通过这种方式判断
console.log('--------Object.prototype.toString--------------')
console.log(Object.prototype.toString.call(false));//[object Boolean]
console.log(Object.prototype.toString.call('哈哈'));//[object String]
console.log(Object.prototype.toString.call(3));//[object Number]
console.log(Object.prototype.toString.call(3n));//[object BigInt]
console.log(Object.prototype.toString.call(Symbol())); //[object Symbol]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]

console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call({}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call(new Map()));//[object Map]
console.log(Object.prototype.toString.call(new Set())); //[object Set]
console.log(Object.prototype.toString.call(new Date())); //[object Date]
console.log(Object.prototype.toString.call(new Error())); //[object Error]

function Person(){}
function Student(){}
Student.prototype = new Person()
var haoxl = new Student()
console.log(Object.prototype.toString.call(haoxl));//[object Object]

参考:

「2021」高频前端面试题汇总之JavaScript篇(上) - 掘金 (juejin.cn)js判断数据类型 - SegmentFault 思否由结果可知typeof可以测试出number、string、boolean、undefined及function,而对于null及数组、对象,typeof均检测出为object,不能进一步判断它们的类型。icon-default.png?t=N7T8https://segmentfault.com/a/1190000015264821

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值