js一共有7种数据类型:6种基本数据类型和1种引用数据类型:
6种基本数据类型包括:String boolean Number Symbol(ES6新增) Undefined Null
1种引用数据类型:Object(在JS中除了基本数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象)
js的常见内置对象:Date,Array,Math,Number,Boolean,String,Array,RegExp,Function…
js原始数据类型和function可以使用typeof区分
typeof function(){}
// "function"
typeof 2
//"number"
typeof ""
//"string"
typeof true
//"boolean"
typeof undefined
//"undefined"
typeof Symbol(2)
// "symbol"
但是,很遗憾的一点是,typeof 在判断一个 object的数据的时候只能告诉我们这个数据是 object, 而不能细致的具体到是哪一种 object。所以要想区分对象、数组、null,单纯使用typeof是不行的。
因为:
typeof null
// "object"
typeof [8]
// "object"
typeof {}
// "object"
综上,typeof 无法区分null 、数组和对象。
instanceof 运算符
在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 “object”。ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。
instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。例如:
var oStringObject = new String("hello world");
alert(oStringObject instanceof String); //输出 "true"
这段代码问的是“变量 oStringObject 是否为 String 对象的实例?”oStringObject 的确是 String 对象的实例,因此结果是 “true”。尽管不像 typeof 方法那样灵活,但是在 typeof 方法返回 “object” 的情况下,instanceof 方法还是很有用的。
当然,instanceof 也可以判断一个实例是否是其父类型或者祖先类型的实例。
let person = function () {
}
let programmer = function () {
}
programmer.prototype = new person()
let nicole = new programmer()
nicole instanceof person // true
nicole instanceof programmer // true
通常我们会区分判断Array和Object
有时会用instanceof 来判断是不是一个对象的实例子
[] instanceof Array
// true 这种方法可以判断数组,但不能区分对象
[] instanceof Object
// true 说明在判断数组上,数据会被instanceof判断为Object
null instanceof Object
// false 说明instanceof也不能区分null
下面介绍一种方法,对每一种数据类型都实用。
Object.prototype.toString.call(function(){})
// "[object Function]"
Object.prototype.toString.call(null)
//"[object Null]"
Object.prototype.toString.call([2])
"[object Array]"
Object.prototype.toString.call(undefined)
//"[object Undefined]"
Object.prototype.toString.call('stjd')
//"[object String]"
Object.prototype.toString.call(1)
//"[object Number]"
Object.prototype.toString.call(true)
//"[object Boolean]"
Object.prototype.toString.call(Symbol(3))
// "[object Symbol]"
Object.prototype.toString.call({q:8})
//"[object Object]"
var reg = /[hbc]at/gi;
Object.prototype.toString.call(reg); // "[object RegExp]"
Object.prototype.toString.call(function(){}); //"[object Function]"//这个方法就建立在js任何类型皆可视为对象
Object.prototype.toString.call()的例外:判断自定义类
function Person(name, age) {
this.name = name;
this.age = age;
}
var person = new Person("Rose", 18);
Object.prototype.toString.call(arr); // "[object Object]"
很明显Object.prototype.toString.call()这种方法不能准确判断person是Person类的实例,而只能用instanceof 操作符来进行判断,如下所示:
console.log(person instanceof Person); // true
再来思考, toString.call([2]) 意思就是改变方法中的this指向,指向传递进去的参数,也就是[2]。那我这样写不是更直观吗?[2].toString()。结果:
[2].toString()
//"2"
var obj = {a: 67}
console.log(obj.toString())
// [object Array]
对比上面两个返回的值是不一样的。这是因为[2].toString()调用的是数组的toSting()方法,而不是对象的toSting()方法。Array改写了Object的toString方法。
toSting.call()实际上就是 Object.prototype.toSting.call()
console.log(Object.prototype.toString.call([33])) // [object Array]
而[2].toSting()实际上是
console.log(Array.prototype.toString.call([2])) //2
使用的过程中,可以这样封装函数
function isType(type) {
return function(obj) {
return {}.toString.call(obj) == "[object " + type + "]"
}
}
var isObject = isType("Object")
var isString = isType("String")
var isArray = Array.isArray || isType("Array")
var isFunction = isType("Function")
var isUndefined = isType("Undefined")
补充:
- 引用类型通常叫做类(class),也就是说,遇到引用值,所处理的就是对象。
- JS数据类型的判断主要有三种方法:typeof、instanceof、Object.prototype.toString.call()
- typeof可以区分原始数据类型和function数据类型
- Object.prototype.toString.call()区分数据类型适用范围最大,但是无法区分自定义对象类型
- 区分自定义对象类型使用instanceof 操作符