JS-数据类型-|JS-数据类型- typeof/instanceof/Object.prototype.toString
参考文章:数据类型typeof 运算符
JavaScript
有三种方法,可以确定一个值到底是什么类型。- typeof运算符
- instanceof运算符
- Object.prototype.toString方法
typeof
运算符可以返回一个值的数据类型。- 数值、字符串、布尔值分别返回
number
、string
、boolean
。
typeof 123 // "number"
typeof '123' // "string"
typeof false // "boolean"
- 函数返回
function
。
function f() {}
typeof f
// "function"
-
undefined
返回undefined
。
typeof undefined
// "undefined"
利用这一点,
typeof
可以用来检查一个没有声明的变量,而不报错。v
// ReferenceError: v is not definedtypeof v
// "undefined"
上面代码中,变量
v
没有用var
命令声明,直接使用就会报错。但是,放在typeof
后面,就不报错了,而是返回undefined
。实际编程中,这个特点通常用在判断语句。
// 错误的写法
if (v) {
// ...
}
// ReferenceError: v is not defined// 正确的写法
if (typeof v === "undefined") {
// ...
}
- 对象返回
object
。
typeof window // "object"
typeof {} // "object"
typeof [] // "object"
typeof
缺点:上面代码中,空数组([])的类型也是object
,这表示在 JavaScript
内部,数组本质上只是一种特殊的对象。 typeof
无法区分数组和对象。这里顺便提一下,
instanceof
运算符可以区分数组和对象。var o = {};
var a = [];
o instanceof Array // false
a instanceof Array // true
- null返回object。因为
null
被认为是一个空的对象的引用。
typeof null // "object"
instanceof
instanceof
运算符返回一个布尔值,表示对象是否为某个构造函数的实例。- 下面代码中,对象
v
是构造函数Vehicle
的实例,所以返回true
。
var v = new Vehicle();
v instanceof Vehicle // true
-
instanceof
运算符的左边是实例对象,右边是构造函数。 -
instanceof
的作用:会检查右边构造函数的原型对象(prototype
),是否在左边对象的原型链上。因此,下面两种写法是等价的。
v instanceof Vehicle
// 等同于
Vehicle.prototype.isPrototypeOf(v)
上面代码中,
Object.prototype.isPrototypeOf
的含义如下:var p = {x:1};
//定义一个原型对象
var o = Object.create(p);
//使用这个原型创建一个对象
p.isPrototypeOf(o);
//=>true:o继承p
Object.prototype.isPrototypeOf(p);
//=> true p继承自Object.prototype
- 由于
instanceof
检查整个原型链,因此同一个实例对象,可能会对多个构造函数都返回true
。
var d = new Date();
d instanceof Date // true
d instanceof Object // true
上面代码中,
d
同时是Date
和Object
的实例,因此对这两个构造函数都返回true
。-
instanceof
的原理是检查右边构造函数的prototype
属性,是否在左边对象的原型链上。有一种特殊情况,就是左边对象的原型链上,只有null
对象。这时,instanceof
判断会失真。
var obj = Object.create(null);
typeof obj // "object"
Object.create(null) instanceof Object // false
上面代码中,
Object.create(null)
返回一个新对象obj
,它的原型是null
(Object.create的详细介绍见后文)。右边的构造函数Object
的prototype
属性,不在左边的原型链上,因此instanceof
就认为obj
不是Object
的实例。但是,只要一个对象的原型不是null
,instanceof
运算符的判断就不会失真。-
instanceof
运算符的一个用处,是判断值的类型。
var x = [1, 2, 3];
var y = {};
x instanceof Array // true
y instanceof Object // true
上面代码中,
instanceof
运算符判断,变量x
是数组,变量y
是对象。【JS-数据类型-|JS-数据类型- typeof/instanceof/Object.prototype.toString】缺点:
instanceof
运算符只能用于对象(纯对象和数组),不适用原始类型(Undefined、Null、Boolean、Number 和 String)的值。var s = 'hello';
s instanceof String // false
上面代码中,字符串不是
String
对象的实例(因为字符串不是对象),所以返回false
。此外,对于
undefined
和null
,instanceOf
运算符总是返回false
。undefined instanceof Object // false
null instanceof Object // false
- 利用
instanceof
运算符,还可以巧妙地解决,调用构造函数时,忘了加new
命令的问题。
function Fubar (foo, bar) {
if (this instanceof Fubar) {
this._foo = foo;
this._bar = bar;
} else {
return new Fubar(foo, bar);
}
}
上面代码使用
instanceof
运算符,在函数体内部判断this
关键字是否为构造函数Fubar
的实例。如果不是,就表明忘了加new
命令。Object.prototype.toString
- 要想区别对象、数组、函数单纯使用
typeof
是不行的。null
和Array
的结果也是object
,有时候我们需要的是 "纯粹" 的object
对象。 - 我们可以通过
Object.prototype.toString
方法准确判断某个对象值属于哪种内置类型。在介绍Object.prototype.toString
方法之前,我们先把toString()
方法和Object.prototype.toString.call()
方法进行对比。
var arr=[1,2];
//直接对一个数组调用toString()
arr.toString();
// "1,2"//通过call指定arr数组调用Object.prototype对象上原始的toString方法
Object.prototype.toString.call(arr);
//"[object Array]"
作为继承的数组
arr
重写了toString
方法,并不是Object.prototype
中的toString
方法。- 为什么
toString
会有不同的作用呢?
其实,这里面就涉及到js
原型及原型链的相关知识
var arr=[1,2,3];
Object.prototype.toString.call(arr);
//"[object Array]"
Array.prototype.toString.call(arr);
// "1,2,3"
arr.toString();
// "1,2,3"
看到这里大家都应该明白了,其实只有
Object.prototype
上的toString
才能用来进行复杂数据类型的判断。- 简单解释一些原型链的概念:
js
中的对象都继承自Object
,所以当我们在某个对象上调用一个方法时,会先在该对象上进行查找,如果没找到则会进入对象的原型(也就是.prototype
)进行查找,如果没找到,同样的也会进入对象原型的原型进行查找,直到找到或者进入原型链的顶端Object.prototype
才会停止。所以,当我们使用
arr.toString()
时,不能进行复杂数据类型的判断,因为它调用的是Array.prototype.toString
。虽然Array
也继承自Object
,但js
在Array.prototype
上重写了toString
,而我们通过Object.prototype.toString.call(arr)
实际上是通过原型链调用了Object.prototype.toString
。- 精确判断对象的类型
JavaScript
中一切都是对象,任何都不例外,对所有值类型应用Object.prototype.toString.call()
方法结果如下:
console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]
推荐阅读
- Docker应用:容器间通信与Mariadb数据库主从复制
- 使用协程爬取网页,计算网页数据大小
- Java|Java基础——数组
- Python数据分析(一)(Matplotlib使用)
- Jsr303做前端数据校验
- Spark|Spark 数据倾斜及其解决方案
- 数据库设计与优化
- 爬虫数据处理HTML转义字符
- 数据库总结语句
- MySql数据库备份与恢复