JavaScript用构造函数如何获取变量的类型名


Posted in Javascript onDecember 23, 2016

使用 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);

这是结果

JavaScript用构造函数如何获取变量的类型名

按照上面的打印结果,总结出下面要注意的几点

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);
 // 结果为假!

JavaScript用构造函数如何获取变量的类型名

使用jQuery中的方法$.type()

现在看看jQuery是怎么做的

// 先申明一个对象,目的是用来做映射
var class2type = {};
// 申明一个core_toString() 的方法,得到最原始的toString() 方法,因为在很多对象中,toStrintg() 已经被重写 
var core_toString() = class2type.toString;
// 这里为 toStrintg() 后的结果和类型名做一个映射,申明一个core_toString() 后的结果,而值就是类型名
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
 class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

因为 Object.prototype.toString() 方法调用结果如下

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) );

JavaScript用构造函数如何获取变量的类型名

上面的打印结果与

class2type[ "[object " + name + "]" ] = name.toLowerCase();

不谋而合!

这是jQuery.type 的核心方法

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" 而不是 "object",所以这里要判断是否是函数,要明白 这里的 typeof obj === function 不是为了函数讨论的,因为函数本身就可以通过typeof 来得到类型.

typeof obj === "object" || typeof obj === "function" ?
 class2type[ core_toString.call(obj) ]

就直接返回class2type 中键值对的结果,,如果不是,那么一定就是基本类型, 通过 typeof 就可以啦.

class2type[ core_toString.call(obj) ] || "object" :
// 这是防止一些未知情况的,如果未取到,就返回object

但是 jQuery.type 有一个很大的缺陷

这是一个自定义类型

function Person(){
 this.name = 'pawn';
}
var p = Person.toString();

// 注意,这里会打印 [object Object],通过上面的方法,无法得到精确的自定义类型

这也是 它的一个大缺陷了!

下面,我们通过构造函数的方式来获取精确类型

通过构造函数来获取类型

这种方式 是蒋坤老师( jk ) 教会我的,非常感谢他.

在理解这个方法之前,需要理解两个点

prorotype 原型属性

我们知道,任何对象或者函数都直接或者间接的继承自Object 或者 Function, (其实最终Function 是继承自 Object 的,这属于原型链的知识了)。那么,任何一个对象都具有原型对象 __proto__ (这个对象只在chrome 和 firefox 暴露,但是在其他浏览器中也是存在的),这个原型对象就是这个对象的构造函数的原型属性(这里可能有点绕).


由于 任何函数都具有 原型属性prototype,并且这个原型属性具有一个默认属性 constructor,它是这个函数的引用,看下面的代码

function Person(){
 this.name = 'pawn';
 }
 console.log(Person.prototype.constructor === Person);

JavaScript用构造函数如何获取变量的类型名

​发现,这两个东西其实一个东西

但是,在某些情况下,需要这么写

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对象封装的方式 也是非常值得研究

Function.prototype.toString()

JavaScript用构造函数如何获取变量的类型名

注意,这里已经不是熟悉 [object Object],而是 已经重写了.

也就是,如果调用一个函数的toString() 方法.那么就会打印这个函数的函数体.

JavaScript用构造函数如何获取变量的类型名

好了,经过上面两个步骤,你明白我要做什么了吗?

如何通过构造函数来获得变量的类型?

判断是否是基本类型

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.log(p.constructor);

JavaScript用构造函数如何获取变量的类型名

现在要做的事 : 如何将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('|' + regex.exec(c)[1] + '|');

JavaScript用构造函数如何获取变量的类型名

使用name

其实,除了上面的正则,每个函数还有一个name属性,返回函数名,但是ie8 是不支持的.

因此上面的代码可以写为:

var getType = function(obj){
 if(obj == null){
 return String(obj);
 }
 if(typeof obj === 'object' || typeof obj === 'function'){ 
 var constructor = obj.constructor;
 if(constructor && constructor.name){
 return constructor.name;
 }
 var regex = /function\s(.+?)\(/;
 return regex.exec(c)[1];
 }else{
 // 如果不是引用类型,那么就是基本;类型
 return typeof obj;
 }
};

但是上面的代码太丑啦,将其简化

简化

var getType = function(obj){
 if(obj == null){
 return String(obj);
 }
 if(typeof obj === 'object' || typeof obj === 'function'){ 
 return obj.constructor && obj.constructor.name.toLowerCase() || 
 /function\s(.+?)\(/.exec(obj.constructor)[1].toLowerCase();
 }else{
 // 如果不是引用类型,那么就是基本类型
 return typeof obj;
 }
};

还是比较麻烦,继续简化

var getType = function(obj){
 if(obj == null){
 return String(obj);
 }
 return typeof obj === 'object' || typeof obj === 'function' ?
 obj.constructor && obj.constructor.name && obj.constructor.name.toLowerCase() ||
 /function\s(.+?)\(/.exec(obj.constructor)[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({}));
console.log(getType(function(){}));
console.log(getType(new Date()));
console.log(getType(new Error()));
console.log(getType( null));
console.log(getType( undefined));

JavaScript用构造函数如何获取变量的类型名

总结

好了,以上就是关于如何获取变量的类型名的全部介绍了,希望本文的内容能对你提供帮助。如果有疑问大家可以留言交流。

Javascript 相关文章推荐
关于IE BUG与字符串截取substr的解决办法
Apr 10 Javascript
js获取电脑分辨率的思路及操作
Nov 22 Javascript
javascript结合canvas实现图片旋转效果
May 03 Javascript
jquery任意位置浮动固定层插件用法实例
May 29 Javascript
js控制文本框输入的字符类型方法汇总
Jun 19 Javascript
详解Javascript数据类型的转换规则
Dec 12 Javascript
js和jquery中获取非行间样式
May 05 jQuery
vue.js简单配置axios的方法详解
Dec 13 Javascript
JavaScript基于面向对象实现的猜拳游戏
Jan 03 Javascript
Webpack 之 babel-loader文件预处理器详解
Mar 23 Javascript
JS实现键值对遍历json数组功能示例
May 30 Javascript
微信小程序单选框自定义赋值
May 26 Javascript
JS中with的替代方法与String中的正则方法详解
Dec 23 #Javascript
Bootstrap源码解读排版(1)
Dec 23 #Javascript
简单实现JS倒计时效果
Dec 23 #Javascript
Bootstrap源码解读下拉菜单(4)
Dec 23 #Javascript
jquery dataview数据视图插件使用方法
Dec 23 #Javascript
基于vue的下拉刷新指令和滚动刷新指令
Dec 23 #Javascript
Bootstrap源码解读按钮(5)
Dec 23 #Javascript
You might like
Dedecms常用函数解析
2008/02/01 PHP
TMDPHP 模板引擎使用教程
2012/03/13 PHP
WordPress自定义时间显示格式
2015/03/27 PHP
php+html5+ajax实现上传图片的方法
2016/05/14 PHP
js HTML5 Canvas绘制转盘抽奖
2020/09/13 Javascript
jQuery.parseHTML() 函数详解
2017/01/09 Javascript
AngularJS 防止页面闪烁的方法
2017/03/09 Javascript
Vue-router路由判断页面未登录跳转到登录页面的实例
2017/10/26 Javascript
JavaScript设计模式之观察者模式(发布订阅模式)原理与实现方法示例
2018/07/27 Javascript
JS打印彩色菱形的实例代码
2018/08/15 Javascript
小程序云开发实战小结
2018/10/25 Javascript
js作用域和作用域链及预解析
2019/04/11 Javascript
layui自定义ajax左侧三级菜单
2019/07/26 Javascript
再也不怕 JavaScript 报错了,怎么看怎么处理都在这儿
2020/12/09 Javascript
解决vue项目本地启动时无法携带cookie的问题
2021/02/06 Vue.js
[46:55]LGD vs Liquid 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/19 DOTA
MySQLdb ImportError: libmysqlclient.so.18解决方法
2014/08/21 Python
python发送HTTP请求的方法小结
2015/07/08 Python
Python数据结构与算法之使用队列解决小猫钓鱼问题
2017/12/14 Python
Python实现的圆形绘制(画圆)示例
2018/01/31 Python
Tensorflow 查看变量的值方法
2018/06/14 Python
Python实用技巧之列表、字典、集合中根据条件筛选数据详解
2018/07/11 Python
python3 自动识别usb连接状态,即对usb重连的判断方法
2019/07/03 Python
在Python中使用MongoEngine操作数据库教程实例
2019/12/03 Python
使用darknet框架的imagenet数据分类预训练操作
2020/07/07 Python
Python基于execjs运行js过程解析
2020/11/27 Python
英国二手iPhone、音乐、电影和游戏商店:musicMagpie
2018/10/26 全球购物
State Cashmere官网:半零售价可持续蒙古羊绒
2020/02/26 全球购物
NET程序员上机面试题
2015/05/23 面试题
实习求职信
2013/12/01 职场文书
社区志愿者心得体会
2014/01/03 职场文书
家长给孩子的表扬信
2014/01/17 职场文书
房屋租房协议书范本
2014/12/04 职场文书
建筑技术负责人岗位职责
2015/04/13 职场文书
phpQuery解析HTML乱码问题(补充官网未列出的乱码解决方案)
2021/04/01 PHP
css height属性中的calc方法详解
2021/06/03 HTML / CSS