概述
一、typeof
typeof
是一个一元运算,放在一个运算数之前,运算数可以是任意类型。它返回值是一个字符串
,该字符串说明运算数的类型。
typeof 100 // number
typeof NaN // number
typeof Infinity // number
typeof true // boolean
typeof 'message' // string
typeof [] // object
typeof {} // object
typeof null // object
typeof function(){} // function
typeof eval // function
typeof Date // function
typeof undefined // undefined
typeof Symbol() // symbol
typeof BigInt(1234567) // bigint
// 基本数据类型:number string boolean null undefined symbol bigint
// 引用数据类型:object(又分为对象、数组、函数)
我们注意到[ ]、{ }、null返回的都是object。所以判断数组类型和null类型时不能用typeof。
为什么typeof null 返回object呢?
typeof null结果是object, 这是个历史遗留bug
第一版的JavaScript是用32位bit来存储值的,且是通过值的低1位或3位来识别类型的。
1:整型(int)
000:引用类型(object)
010:双精度浮点型(double)
100:字符串(string)
110:布尔型(boolean)
另外还用两个特殊值:
1.undefined,用整数−2^30(负2的30次方,不在整型的范围内)
2.null,机器码空指针(C/C++ 宏定义),低三位也是000
这32位有1-3位表示TYPE TAG,其它位表示真实值 而表示object的标记位正好是低三位都是0(000: object). 而js 里的Null 是机器码NULL空指针,所以空指针引用加上对象标记还是0,最终体现的类型还是object…
二、instanceof
instanceof
是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。 在这里需要特别注意的是:instanceof 检测的是原型。
// 用一段伪代码来模拟其内部执行过程。
const instanceof = (A, B) => A.__proto__ === B.prototype
100 instanceof Number // false
true instanceof Boolean // false
'message' instanceof String // false
null instanceof Object // false
[] instanceof Array // true
{} instanceof Object // true
function(){} instanceof Function // true
new Number(100) instanceof Number // true
new Boolean(true) instanceof Boolean // true
new String('message') instanceof String // true
function Person() {}
const p1 = new Person()
p1 instanceof Person // true
function Car() {}
const car1 = new Car()
car1 instanceof Car // true
[] instanceof Object // true
[] instanceof Array // true
[ ] instanceof Object 和 [ ] instanceof Array 都是返回 true。为什么会这样呢?
- [ ] .__proto__ 指向 Array.prototype
- Array.prototype.__proto__ 指向 Object.prototype
- Object.prototype.__proto__ 最终指向 null
[ ]、Array 和 Object 三者内部存在完整的原型链。
从原型链可以看出,[ ] 的 __proto__ 直接指向 Array.prototype,间接指向 Object.prototype,所以按照 instanceof 的判断规则,[ ] 就是 Object 的实例
因此,instanceof 只能用来判断两个对象
是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。所有你会发现基本数据类型 用 instanceof 判断时都会返回 false。
三、constructor
当一个函数 Person 被定义时,JS引擎会为 Person 添加 prototype 原型,然后再在 prototype 上添加一个 constructor 属性,并让其指向 F 的引用。如下所示:
当执行 const p = new Person() 时,Person 被当成了构造函数,p 是 Person 的实例对象,此时 Person 原型上的 constructor 传递到了 p 上,因此 p.constructor === Person
(100).constructor === Number // true
true.constructor === Boolean // true
('message').constructor === String // true
([]).constructor === Array // true
(function() {}).constructor === Function // true
({}).constructor === Object // true
- null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。
- 需要注意的是,如果创建一个对象来改变它的原型,constructor 就不能用来判断数据类型了。
function Person() {}
const p1 = new Person()
p1.constructor === Person // true
Person.prototype = new Array()
// Person.prototype = { xx: 'yy' }
const p2 = new Person()
p2.constructor === Person // false
p2.constructor === Array // true
// p2.constructor === Object
// 为什么变成了 Object?
// 因为 prototype 被重新赋值的是一个 { }, { } 是 new Object() 的字面量,因此 new Object() 会将 Object 原型上的 constructor 传递给 { },也就是 Object 本身。
// 因此,在重写对象原型时一般都需要重新给constructor赋值,以保证对象实例的类型不被篡改
四、Object.prototype.toString.call()
toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为
[object Xxx] ,其中 Xxx 就是对象的类型。对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call
/ apply 来调用才能返回正确的类型信息。
const a = Object.prototype.toString
a.call(100) // [object Number]
a.call(true) // [object Boolean]
a.call('message') // [object String]
a.call([]) // [object Array]
a.call({}) // [object Object]
a.call(function() {}) // [object Function]
a.call(null) // [object Null]
a.call(undefined) // [object Undefined]
a.call(Symbol()) // [object Symbol]
a.call(BigInt(1000000)) // [object BigInt]
a.call(new Date()) // [object Date]
同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?
这是因为toString为Object的原型方法,而Array,function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型)所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。
即使改变它的原型,也还能正确判断。
function Person() {}
Person.prototype = new Array()
Object.prototype.toString.call(Person) // [object Function]
最后
以上就是勤奋蜡烛为你收集整理的js数据类型检测的方式有哪些?的全部内容,希望文章能够帮你解决js数据类型检测的方式有哪些?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复