专题汇总-数据类型检测
- typeof
- instanceof & constructor
- Object.prototype.toString.call([value])
- 封装一个数据类型检测的方法库
typeof
/*
typeof:用来检测数据类型的运算符
typeof [value]
@return
首先是个字符串
字符串中包含对应的数据类型,例如:"number","string","object","boolean","undefeined","symbol","function"
@局限性
不能具体区分对象数据类型的值
typeof null //"object"
typeof [] //"object"
typeof {} //"object"
typeof /^$/ //"object"
@优势
使用方便,所以在真实项目中,我们也会大量应用它来检测,尤其是在检测基本类型值(除null之外)和函数类型值的时候,它还是很方便的
*/
function func(n,m,callback){
//=>ES6:func(n=0,m=0)
//=>检测形参的值是否为undefined
n === "undefined"? n=0 : null;
typeof m ==="undefined" ? m=0 : null;
//=>基于逻辑或逻辑与处理(瑕疵:不仅仅是不传赋值默认值,如果传递的值是假也会处理成默认值)
//n = n || 0;
//m = m || 0;
/*回调函数执行*/
typeof callback ==="function" ? callback() : null;
}
typeof undefined; //"undefined"
typeof true; //"boolean"
typeof false; //"boolean"
typeof 6; //"number"
typeof 6.5; //"number"
typeof NaN; //"number"
typeof "LBJhui"; //"string"
typeof 'LBJhui'; //"string"
hello = function(){};
typeof hello; //"function"
typeof Symbol; //"function"
typeof new Function(); //"function"
typeof []; //"object"
typeof {}; //"object"
typeof null; //"object"
typeof new Array(); //"object"
typeof new Object(); //"object"
typeof new Error(); //"object"
typeof new Number(); //"object"
typeof new String(); //"object"
typeof new Date(); //"object"
typeof new RegExp(); //"object"
返回一个小写字母的类型字符串
只需要一个操作数
简单数据类型或者函数或者对象
在 ECMAScript 2015 之前,typeof
总能保证对任何所给的操作数返回一个字符串。即便是没有声明的标识符,typeof
也能返回 'undefined'
。使用 typeof
永远不会抛出错误。
但在加入了块级作用域的 let
和 const 之后,在其被声明之前对块中的 let
和 const
变量使用 typeof
会抛出一个 ReferenceError。块作用域变量在块的头部处于“暂存死区”,直至其被初始化,在这期间,访问变量将会引发错误。
typeof undeclaredVariable === 'undefined';
typeof newLetVariable; // ReferenceError
typeof newConstVariable; // ReferenceError
typeof newClass; // ReferenceError
let newLetVariable;
const newConstVariable = 'hello';
class newClass{};
instanceof & constructor
/*
instanceof:本意是用来检测实例是否隶属于某个类的运算符,我们基于这样的方式,也可以用来做某些数据类型的检测,例如:数组、正则等
@局限性
不能处理基本数据类型
只要在当前实例的原型链(__proto__)中出现过的类,检测结果都是true(用户可能会手动修改原型链的指向:example.__proto__ 或者 在类的继承中 等情况)
*/
let arr[],
reg = /^$/,
obj = {};
arr instanceof Array; //true
reg instanceof Array; //false
arr instanceof Object; //true
obj instanceof Array; //false
1 instanceof Number; //false
//创建值的两种方式(不管哪种方式都是所属于类的实例)
//字面量:let n = 12;
//构造函数:let m = new Number("12")
function func(){
argument instanceof Array; //false
argument.__proto__ = Array.prototype
argument instanceof Array; //true
}
/*
constructor:构造函数
@原理:在类的原型上一般都会带有constructor属性,存储当前类本身,我们也是利用这一点,获取某类的实例constructor属性值,验证是否为所属的类,从而进行数据类型检测
@局限性:constructor属性值太容易被修改了
*/
let n = 12;
let arr = [];
n.constructor; //ƒ Number() { [native code] }
n.constructor === Number; //true
arr.constructor === Array; //true
arr.constructor === Object; //false
arr.constructor = 111;//设置私有属性
arr.constructor === Array; //false
Func.prototype = {}; //这样原型上没有constructor属性(重构了)
a = new Number(888);
a instanceof Number; //true
b = new String('LBJhui');
b instanceof String; //true
c = new Array(6,66,666);
c instanceof Array; //true
d = new Object();
d instanceof Object; //true
"LBJhui" instanceof String; //false
888 instanceof Number; //false
true instanceof Boolean; //false
[1,2] instanceof Array; //true
var person = {name:"LBJhui",gender:"male"};
person instanceof Object; //true
new Number(888) instanceof Number; //true
以上结果显示,直接的字面量值判断数据类型,只有引用数据类型(Array,Function,Object)被精准判断,其他(Number,Boolean,String)字面值不能被instanceof精准判断。
需要注意的是,如果表达式 obj instanceof Foo
返回 true
,则并不意味着该表达式会永远返回 true
,因为 Foo.prototype
属性的值有可能会改变,改变之后的值很有可能不存在于 obj
的原型链上,这时原表达式的值就会成为 false
。另外一种情况下,原表达式的值也会改变,就是改变对象 obj
的原型链的情况,虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的 __proto__
伪属性,是可以实现的。比如执行 obj.__proto__ = {}
之后,obj instanceof Foo
就会返回 false
了。
instanceof来判断null和undefined,浏览器在这里报错了,它认为null,undefined不是构造器。
... | typeof | instanceof |
---|---|---|
作用 | 检测数据类型 | 检测对象之间的关联性 |
返回 | 小写字母字符串 | 布尔值 |
操作数 | 简单数据类型、函数或者对象 | 左边必须是引用类型,右边必须是函数 |
操作数个数 | 1个 | 2个 |
Object.prototype.toString.call([value])
/*
Object.prototype.toString.call([value]):调用Object原型上的toString方法,让方法执行的时候,方法中的this是要检测的数据类型,从而获取到数据类型所属类的详细信息
toString() 方法返回一个表示该对象的字符串。
@信息的模板
"[object 所属类]",例如:"[object Array]"
在所有的数据类型类中,它们的原型上都有toString方法,除Object.prototype.toString不是把数据值转换为字符串,其余的都是转换为字符串,而Object原型上的toString是检测当前实例隶属类的详细信息的(检测数据类型)
obj.toString()
1.首先基于原型链查找机制,找到Object.prototype.toString
2.把找到的方法执行,方法中的this->obj
3.方法内部把this(obj)的所属类信息输出
=>方法执行,方法中的this是谁,就是检测谁的所属类信息
这个方法很强大, 所有数据类型隶属于的类信息检测的一清二楚
Number/String/Boolean/Null/Undefined/Symbol/Object/Array/RegExp/Data/Math/Function...
*/
[12,23].toString(); //"12,23"
/^\d+$/.toString(); //"/^\d+$/"
(function anonymous(){}).toString(); //"function anonymous(){}"
let obj1 = {},
obj2 = {
name:"LBJhui"
}
obj1.toString(); //"[object Object]"
obj2.toString(); //"[object Object]"
let obj = {};
obj.toString.call(100) //"[object Number]"
Object.prototype.toString.call(100) //"[object Number]"
let _obj ={};
toString = _obj.toString;
toString.call();
每个对象都有一个 toString()
方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString()
方法被每个 Object
对象继承。如果此方法在自定义对象中未被覆盖,toString()
返回 "[object type]",其中 type
是对象的类型。以下代码说明了这一点:
var o = new Object();
o.toString(); // returns [object Object]
可以通过 toString()
来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString()
来检测,需要以 Function.prototype.call()
或者 Function.prototype.apply()
的形式来调用,传递要检查的对象作为第一个参数,称为 thisArg
。
var toString = Object.prototype.toString;
toString.call(333); // [object Number]
toString.call("aaa"); // [object String]
toString.call(true); // [object Boolean]
toString.call([]); // [object Array]
toString.call(function(){}); // [object Function]
toString.call({}); // [object Object]
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
// 甚至于js的内置对象也能被精确判断
toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
封装一个数据类型检测的方法库
let _obj = {
isNumeric:"Number",
isBoolean:"Boolean",
isString:"String",
isNull:"Null",
isUndefined:"Undefined",
isSymbol:"Symbol",
isPlainObject:"Object",
isArray:"Array",
isRegExp:"RegExp",
isDate:"Date",
isFunction:"Function",
isWindow:"Window"
},
_toString.call(val) = _obj.toString;
_type = {};
for(let key in _obj){
if(!_obj.hasOwnProperty(key)) break;
//key =isNumeric
//_obj[key]="Number"
//val=12
let reg = new RegExp("\\[Object" + _obj[key] + "\\]");
_type[key] = function anonymous(val){
return reg.test(_toString.call(val));
}
}
网友评论