在ES5的时候,js的数据类型分为两种:原始类型(即基本数据类型)和对象类型(即引用数据类型)。
基本数据类型
包括 String、Number、Boolean、Undefined、Null;
引用数据类型
也就是对象类型Object,比如:Object、Array、Function、Data等;
ES6 中新增了一种基本数据类型 Symbol ,用来表示独一无二的值。
let fc1 = '字符串' // String
let fc2 = 12 // Number
let fc3 = true // Boolean
// fc4 咱不声明变量fc4,所以fc4的数据类型是 Undefined
let fc5 = null // Null
let fc6 = {a: 1} // Object
let fc7 = [1, 2, 3] // Array
let fc8 = () => {} // Function
let fc9 = new Date() // Date (Object)
let fc10 = Symbol() // Symbol
typeof
最常见的判断方法
typeof是一个操作符,右侧跟一个一元表达式,返回这个表达式的数据类型,以字符串的形式表示;
typeof fc1 // 'string' ------------------ '字符串'
typeof fc2 // 'number' ------------------ 12
typeof fc3 // 'boolean' ----------------- true
typeof fc4 // 'undefined' --------------- undefined(未声明)
typeof fc5 // 'object' ------------------ null
typeof fc6 // 'object' ------------------ {a: 1}
typeof fc7 // 'object' ------------------ [1, 2, 3]
typeof fc8 // 'function' ---------------- () => {}
typeof fc9 // 'object' ------------------ new Date()
typeof fc10 // 'symbol' ----------------- Symbol()
注意:
1、typeof可以测试出Number、String、Boolean、Symbol、Undefined及Function,而对于Null、Array、Object,typeof均检测出为‘object’,不能进一步判断它们的类型;
2、typeof new Date()、typeof new RegExp()、typeof new Error()都会返回 'object';
3、typeof NaN会返回 'Number',NaN也是Number的一种;
instanceof
判断已知对象类型的方法
利用instanceof来判断A是否为B的实例,表达为A instanceof B,返回一个布尔值。instanceof的原理是通过检测对象的原型链上是否含有类型的原型。
fc6 instanceof Object // true ------------------ {a: 1}
fc7 instanceof Array // true ------------------- [1, 2, 3]
fc9 instanceof Date // true -------------------- new Date()
注意:
instanceof 后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。
Object.prototype.toString
通用但很繁琐的方法
Object.prototype.toString 方法能有效弥补typeof不能很好区分数组、对象和函数。
每个类在内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。
Object.prototype.toString 的原理是当调用的时候,就取值内部的 [[Class]] 属性值, 然后拼接成 '[object ' + [[Class]] + ']' 这样的字符串并返回,然后我们使用 call 方法来获取任何值的数据类型。
Object.prototype.toString.call(fc1) // '[object String]' ------------------ '字符串'
Object.prototype.toString.call(fc2) // '[object Number]' ------------------ 12
Object.prototype.toString.call(fc3) // '[object Boolean]' ----------------- true
Object.prototype.toString.call(undefined) // '[object Undefined]' --------- undefined(未声明)
Object.prototype.toString.call(fc5) // '[object Null]' -------------------- null
Object.prototype.toString.call(fc6) // '[object Object]' ------------------ {a: 1}
Object.prototype.toString.call(fc7) // '[object Array]' ------------------- [1, 2, 3]
Object.prototype.toString.call(fc8) // '[object Function]' ---------------- () => {}
Object.prototype.toString.call(fc9) // '[object Date]' -------------------- new Date()
Object.prototype.toString.call(fc10) // '[object Symbol]' ----------------- Symbol()
constructor
JS规定,每个构造函数都会有一个prototype属性,即为构造函数的原型对象,而原型对象中会有一个constructor属性指回到构造函数。当利用构造函数创建新对象时,原型上的constructor属性也会被遗传到新创建的对象上,从原型链的角度讲,构造函数也代表了对象的类型。
fc1.constructor === String // true ------------------ '字符串'
fc2.constructor === Number // true ------------------ 12
fc3.constructor === Boolean // true ----------------- true
fc6.constructor === Object // true ------------------ {a: 1}
fc7.constructor === Array // true ------------------- [1, 2, 3]
fc8.constructor === Function // true ---------------- () => {}
fc9.constructor === Date // true -------------------- new Date()
fc10.constructor === Symbol // true ----------------- Symbol()
注意:
1、undefined和null没有contructor属性;
2、constructor 在类继承时会出错;
其他数据类型判断函数
Array.isArray()
用于确定传递的值是否是一个Array。如果对象是Array,则返回true,否则为false。
Array.isArray([1, 2, 3]);
// true
Array.isArray({foo: 123});
// false
Array.isArray("foobar");
// false
Array.isArray(undefined);
// false
isNaN() 和 Number.isNaN()
isNaN()函数用来确定一个值是否为 NaN。
与 JavaScript 中其他的值不同, NaN不能通过相等操作符(== 和 ===)来判断 ,因为 NaN == NaN 和 NaN === NaN 都会返回 false。 因此,isNaN 就很有必要了。
isNaN(NaN); // true
// 看似很完美,但是接着看以下例子
isNaN('A String'); // true
isNaN(undefined); // true
isNaN({}); // true
会发现,很明显不是 NaN 的 value 也被误判成 NaN 了。
这个BUG已经存在了20年,从JavaScript最开始就一直存在。很明显当初的设计者,在设计isNaN()的时候,局限了在 "Not a Number" 这一字面意思上了:只要不是number就会返回 true。
于是 ES6 为了弥补这一BUG(而不是修正,因为isNaN存在时间太长,有可能很多功能都是基于这个BUG之上的)引入了 Number.isNaN().
Number.isNaN(NaN); // true
Number.isNaN('A String'); // false
Number.isNaN(undefined); // false
Number.isNaN({}); // false
没有ES6的情况下,可以采用以下polyfill
if (!Number.isNaN) {
Number.isNaN = function(n) {
return (
typeof n === "number" &&
window.isNaN( n )
);
};
}