S数据类型的分类和判断
在前端笔试⾯试中“JS数据类型的分类和判断”是⾼频的基础考点,今天总结⼀下,对正在准备⼯作的⼩伙伴应该有所帮助~
JavaScript中有6种数据类型:数字(number)、字符串(string)、布尔值(boolean)、undefined、null、对象(Object)。其中对象类型包括:数组(Array)、函数(Function)、还有两个特殊的对象:正则(RegExp)和⽇期(Date)。
⼀、分类
从不同的⾓度对6种数据类型进⾏分类:
⼆、判断
1、typeof
typeof返回⼀个表⽰数据类型的字符串,返回结果包括:number、string、boolean、object、undefined、function。typeof可以对基本类型number、string  、boolean、undefined做出准确的判断(null除外,typeof null===“object”,这是由于历史的原因,我就不巴拉巴拉了,其实我也说不清楚?);⽽对于引⽤类型,除了function之外返回的都是object。但当我们需要知道某个对象的具体类型
时,typeof就显得有些⼒不从⼼了。
typeof 1; // number 有效
typeof ‘ ’;//string 有效
typeof true; //boolean 有效
typeof undefined; //undefined 有效
typeof null; //object ⽆效
typeof new Function(); // function 有效
typeof [] ; //object ⽆效
typeof new Date(); //object ⽆效
typeof new RegExp(); //object ⽆效
复制代码
2、instanceof
当我们需要知道某个对象的具体类型时,可以⽤运算符 instanceof,instanceof操作符判断左操作数对象的原型链上是否有右边这个构造函数的prototype属性,也就是说指定对象是否是某个构造函数的实例,最后返回布尔值。 检测的我们⽤⼀段伪代码来模拟instanceof内部执⾏过程:
instanceof (A,B) = {
var L = A.__proto__;
var R = B.prototype;
if(L === R) {
//A的内部属性__proto__指向B的原型对象
return true;
}
return false;
}
复制代码
从上述过程可以看出,当 A 的 __proto__ 指向 B 的 prototype 时,就认为A就是B的实例,我们再来看⼏个例⼦:
[] instanceof Array; //true
[] instanceof Object; //true
new Date() instanceof Date;//true
new Date() instanceof Object;//true
function Person(){};
new Person() instanceof Person;//true
new Person() instanceof Object;//true
复制代码
我们发现,虽然 instanceof 能够判断出 [] 是Array的实例,但它认为 [] 也是Object的实例,为什么呢? 我们来分析⼀下[]、Array、Object 三者之间的关系: 从instanceof 能够判断出 [].__proto__ 指向 Array.prototype, ⽽ Array.prototype.__proto__ ⼜指向了Object.prototype,Object.prototype.__proto__ 指向了null,标志着原型链的结束。因此,[]、Array、Object就形成了如下图所⽰的⼀条原型链:
从原型链可以看出,[] 的 __proto__  直接指向Array.prototype, 间接指向Object.prototype, 所以按照 in
stanceof 的判断规则,[] 就是Object的实例。
注意:instanceof运算符只能⽤于对象,不适⽤原始类型的值。
'hello' instanceof String // false
null instanceof Object // false
undefined instanceof Object // false
复制代码
字符串、null和undefined不是对象,所以返回false。
3、constructor
constructor属性的作⽤是,可以得知某个实例对象,到底是哪⼀个构造函数产⽣的。
var f = new F();
复制代码
但是 constructor 属性易变,不可信赖,这个主要体现在⾃定义对象上,当开发者重写prototype后,原有的constructor会丢失。
function F() {}
F.prototype = {
_name: 'Eric',
};
var f = new F();
复制代码
因此,为了规范,在重写对象原型时⼀般都需要重新给constructor赋值,以保证实例对象的类型不被改写。
function F() {}
F.prototype = {
constructor: F,
_name: 'Eric',
};
var f = new F();
复制代码
4、String
toString是Object原型对象上的⼀个⽅法,该⽅法默认返回其调⽤者的具体类型,更严格的讲,是 toString运⾏时this指向的对象类型, 返回的类型格式为[object,xxx],xxx是具体的数据类型,其中包括:
String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,... 基本上所有对象的类型都可以通过这个⽅法获取到。
String.call('') ;  // [object String]
String.call(1) ;    // [object Number]
String.call(true) ; // [object Boolean]
String.call(undefined) ; // [object Undefined]
String.call(null) ; // [object Null]
String.call(new Function()) ; // [object Function]
String.call(new Date()) ; // [object Date]
String.call([]) ; // [object Array]
String.call(new RegExp()) ; // [object RegExp]
String.call(new Error()) ; // [object Error]
String.call(document) ; // [object HTMLDocument]
String.call(window) ; //[object Window]
复制代码
需要注意的是,必须通过String.call来获取,⽽不能直接 new Date().toString(), 从原型链的⾓度讲,所有对象的原型链最终都指向了Object, 按照JS变量查规则,其他对象应该也可以直接访问到Object的toString⽅法,⽽事实上,⼤部分的对象都实现了⾃⾝的toString⽅法,这样就可能会导致Object的toString被终⽌查,因此要⽤call来强制执⾏Object的toString⽅法。
三、总结:
typeof可以准确地判断出基本类型,但是对于引⽤类型除function之外返回的都是object;
已知是引⽤类型的情况可以选⽤instanceof或constructor⽅法进⾏具体类型的判断:
instanceof是基于原型链的;
object toconstructor 属性易变,不可信赖,为了规范,在重写对象原型时⼀般都需要重新给constructor赋值,以保证实例对象的类型不被改写;String.call() 通⽤但很繁琐。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。