JavaScript⽤构造函数如何获取变量的类型名
typeof array使⽤ typeof 获取基本的类型
看到题⽬的第⼀眼,有些同学可能会想到 typeof 运算符,在JavaScript语⾔中,给出了使⽤ typeof 运算符来获取基本的类型名.(注意不是基本类型)
这是 typeof 的全部⽤法
01-typeof.htm
console.log('typeof of 10 ~~~~' +typeof 10);
console.log('typeof of "a" ~~~~' +typeof 'a');
console.log('typeof of true ~~~~' +typeof true);
console.log('typeof of {} ~~~~' +typeof {});
console.log('typeof of /123/ ~~~~' +typeof /123/);
console.log('typeof of function(){} ~~~~' +typeof function(){});
console.log('typeof of undefined ~~~~' +typeof undefined);
console.log('typeof of null ~~~~' +typeof null);
这是结果
按照上⾯的打印结果,总结出下⾯要注意的⼏点
typeof (引⽤类型) 除了函数, 都是 'object',⽐如 typeof /123/
typeof null 为'object'
typeof undefined 为 'undefined',通常, 如果使⽤两等号, null == undefined为真.
转换为数字的常见⽤法 "10"-0, 如果没有转换成功,返回NaN,由于NaN 的⼀个特性: NaN != NaN ,故判断转换成功与否的常见做法: (这也是我参见 jQuery的源码发现的,jQuery源码读100遍都不为过)
("10x" - 0) == ("10x" - 0);
// 结果为假!
使⽤jQuery中的⽅法$.type()
现在看看jQuery是怎么做的
// 先申明⼀个对象,⽬的是⽤来做映射
var class2type = {};
// 申明⼀个core_toString() 的⽅法,得到最原始的toString() ⽅法,因为在很多对象中,toStrintg() 已经被重写
var core_toString() = String;
// 这⾥为 toStrintg() 后的结果和类型名做⼀个映射,申明⼀个core_toString() 后的结果,⽽值就是类型名
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = LowerCase();
});
因为String() ⽅法调⽤结果如下
var core_toString = {}.toString;
console.log( core_toString.call(1) );
console.log( core_toString.call("11") );
console.log( core_toString.call(/123/) );
console.log( core_toString.call({}) );
console.log( core_toString.call(function(){}) );
console.log( core_toString.call([]) );
console.log( core_toString.call(true) );
console.log( core_toString.call(new Date()) );
console.log( core_toString.call(new Error() ));
console.log( core_toString.call(null) );
console.log( core_toString.call(undefined) );
console.log( String(null) );
console.log( String(undefined) );
上⾯的打印结果与
class2type[ "[object " + name + "]" ] = LowerCase();
不谋⽽合!
这是pe 的核⼼⽅法
type: function( obj ) {
if ( obj == null ) {
return String( obj );
}
// Support: Safari <= 5.1 (functionish RegExp)
return typeof obj === "object" || typeof obj === "function" ?
class2type[ core_toString.call(obj) ] || "object" :
typeof obj;
},
注意,为什么把 null 或者 undefined 单独讨论呢,因为在⼀些版本浏览器中
console.log(core_toString.call(null));
console.log(core_toString.call(undefined));
这是会报错的!
如果是对象类型,另:由于在⼀些低版本的浏览器中,typeof /123/ 会返回的是 "function" ⽽不是 "objec
t",所以这⾥要判断是否是函数,要明⽩这⾥的typeof obj === function不是为了函数讨论的,因为函数本⾝就可以通过typeof 来得到类型.
typeof obj === "object" || typeof obj === "function" ?
class2type[ core_toString.call(obj) ]
就直接返回class2type 中键值对的结果,,如果不是,那么⼀定就是基本类型, 通过 typeof 就可以啦.
class2type[ core_toString.call(obj) ] || "object" :
// 这是防⽌⼀些未知情况的,如果未取到,就返回object
但是 pe 有⼀个很⼤的缺陷
这是⼀个⾃定义类型
function Person(){
this.name = 'pawn';
}
var p = String();
// 注意,这⾥会打印 [object Object],通过上⾯的⽅法,⽆法得到精确的⾃定义类型
这也是它的⼀个⼤缺陷了!
下⾯,我们通过构造函数的⽅式来获取精确类型
通过构造函数来获取类型
这种⽅式是蒋坤⽼师( jk ) 教会我的,⾮常感谢他.
在理解这个⽅法之前,需要理解两个点
prorotype 原型属性
我们知道,任何对象或者函数都直接或者间接的继承⾃Object 或者 Function,(其实最终Function 是继承⾃ Object 的,这属于原型链的知识了)。那么,任何⼀个对象都具有原型对象 __proto__ (这个对象只在chrome 和 firefox 暴露,但是在其他浏览器中也是存在的),这个原型对象就是这个对象的构造函数的原型属性(这⾥可能有点绕).
由于任何函数都具有原型属性prototype,并且这个原型属性具有⼀个默认属性 constructor,它是这个函数的引⽤,看下⾯的代码function Person(){
this.name = 'pawn';
}
console.log(structor === Person);
发现,这两个东西其实⼀个东西
但是,在某些情况下,需要这么写
function Person(){
this.name = 'pawn';
}
Person.protype = {
XX: ... ,
xx: ... ,
...
}
这么做,就会覆盖原本的 protype ⽅法,那么construcor 就不存在了,这是,必须要显⽰的申明这个对象
Person.protype = {
construction: Person,
XX: ... ,
xx: ... ,
...
}
在jQuery的中,就是这么做的,
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
var match, elem;
关于 jQuery对象封装的⽅式也是⾮常值得研究
String()
注意,这⾥已经不是熟悉 [object Object],⽽是已经重写了.
也就是,如果调⽤⼀个函数的toString() ⽅法.那么就会打印这个函数的函数体.
好了,经过上⾯两个步骤,你明⽩我要做什么了吗?
如何通过构造函数来获得变量的类型?
判断是否是基本类型
var getType = function(obj){
if(obj == null){
return String(obj);
}
if(typeof obj === 'object' || typeof obj === 'fucntion'){
...
}else{
// 如果不是引⽤类型,那么就是基本类型
return typeof obj
}
}
如果是对象或者函数类型
function Person(){
this.name = 'pawn';
}
var p = new Person();
console.structor);
现在要做的事 : 如何将Person 提取出来呢?
⽏庸置疑,字符串切割那⼀套肯定可以办到,但是太 low 啦!
这⾥,我使⽤正则将Person提取出来
var regex = /function\s(.+?)\(/
function Person(){
this.name = 'pawn';
}
var p = new Person();
var c = p.constructor
var regex = /function\s(.+?)\(/;
console.log('|' + (c)[1] + '|');
使⽤name
其实,除了上⾯的正则,每个函数还有⼀个name属性,返回函数名,但是ie8 是不⽀持的.因此上⾯的代码可以写为:
var getType = function(obj){
if(obj == null){
return String(obj);
}
if(typeof obj === 'object' || typeof obj === 'function'){
var constructor = structor;
if(constructor && constructor.name){
return constructor.name;
}
var regex = /function\s(.+?)\(/;
(c)[1];
}else{
// 如果不是引⽤类型,那么就是基本;类型
return typeof obj;
}
};
但是上⾯的代码太丑啦,将其简化
简化
var getType = function(obj){
if(obj == null){
return String(obj);
}
if(typeof obj === 'object' || typeof obj === 'function'){
structor && LowerCase() ||
/
function\s(.+?)\(/.structor)[1].toLowerCase();
}else{
// 如果不是引⽤类型,那么就是基本类型
return typeof obj;
}
};
还是⽐较⿇烦,继续简化
var getType = function(obj){
if(obj == null){
return String(obj);
}
return typeof obj === 'object' || typeof obj === 'function' ?
/function\s(.+?)\(/.structor)[1].toLowerCase():
typeof obj;
};
好了,已经全部弄完了,写个代码测试⼀下:
function Person(){
this.name = 'pawn';
}
var p = new Person();
console.log(getType(p));
console.log(getType(1));
console.log(getType("a"));
console.log(getType(false));
console.log(getType(/123/));
console.log(getType({}));
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论