为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

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

2018-05-01 18页 doc 101KB 16阅读

用户头像

is_977556

暂无简介

举报
JavaScript使用构造函数获取变量的类型名JavaScript使用构造函数获取变量的类型名 这个题很有意思, x 想想为啥,, 有时会看到: Object.prototype.toString.call() toString()是一个怎样的方法,他定义在哪里呢, 很多人就会在想,为神马 获取对象类型,为什么用 Object.prototype.toString.call(obj) 而不 用 obj.toString() 呢, 参考: 其实说白了,就是怕你重写了toString,所以才要用object 最原始的他toString,所以才去c...
JavaScript使用构造函数获取变量的类型名
JavaScript使用构造获取变量的类型名 这个题很有意思, x 想想为啥,, 有时会看到: Object.prototype.toString.call() toString()是一个怎样的方法,他定义在哪里呢, 很多人就会在想,为神马 获取对象类型,为什么用 Object.prototype.toString.call(obj) 而不 用 obj.toString() 呢, 参考: 其实说白了,就是怕你重写了toString,所以才要用object 最原始的他toString,所以才去call: 1 2 3 4 5 6 21 22 23 24 1 html> 3 4 5 6 25 26 27 28 至于为啥,,,看 它是能将某一个值转化为字符串的方法。然而它是如何将一个值从一种类型转化为字符串类型的呢, 通过下面几个例子,我们便能获得: 1.将boolean类型的值转化为string类型: console.log(true.toString());//"true"console.log(false.toString());//"false" 2.将string类型按其字面量形式输出: var str = "test123y";console.log(str.toString());//"test123y" 3.将Object类型转化成string类型(JavaScript原生的Array类型、Date类型、RegExp类型 以及Number、Boolean、String这些包装类型都是Object的子类型): 自定义Object类型(没有重新定义toString方法): var obj = {name:"Tom", age:18};console.log(obj.toString());//"[object Object]"此时调用的是从Object继承来的原始的toString()方法 接下来的三个例子都是以重写的方式实现了toString()方法; 1.Array类型: var arr = ["tom",12,"rose",18];console.log(arr.toString());//"tom,12,rose,18" 2.RegExp类型 var patten = new RegExp("//[hbc//]at", "gi");console.log(patten.toString());//"//[hbc/]at/gi" 3.Date类型 var date = new Date(2014,02,26);//注意这种创建的日期,其月份是3 月console.log(date.toString());//"Wed Mar 26 2014 00:00:00 GMT+0800"输出格式因浏览器不同而不同,此为firefox的输出格式; 4.Number类型也是以重写的方式实现toString()方法的,请看以下例子: (1)它可以接受一个整数,并将调用这个方法的数值转化成相应进制的字符串: var num = 16;console.log(num.toString(2));//10000 二进制 console.log(num.toString(8));//20 八进制 console.log(num.toString(16));//10 十六进制 console.log(num.toString(5));//31 虽然没有五进制,但是这样传参是可以被 toString()方法接受的 (2)再看下面的代码: console.log(1.toString());//这种写法会报错语法错误,但是下面的写法都是 合法的;console.log((1).toString());//"1"console.log(typeof (1).toString());//stringconsole.log(1..toString());//"1"console.log(typeof (1).toString());//stringconsole.log(1.2.toString());//"1"console.log(typeof (1).toString());//string 这是因为javascript引擎在解释代码时对于“1.toString()”认为“.”是浮点符号,但因小数点后面的 字符是非法的,所以报语法错误;而后面的“1..toString()和1.2.toStirng()”写法,javascript引 擎认为第一个“.”小数点,的二个为属性访问语法,所以都能正确解释执行;对于“(1).toStirng()” 的写法,用“()”排除了“.”被视为小数点的语法解释,所以这种写法能够被解释执行; (3)纯小数的小数点后面有连续6或6个以上的“0”时,小数将用e示法进行输出; var num = 0.000006;//小数点后面有5个 “0”console.log(num.toString());//"0.000006"var num = 0.0000006;//小数点后面有6个“0”console.log(num.toString());//"6e-7" (4)浮点数整数部分的位数大于21时,输出时采用e表示法; var num = 1234567890123456789012;console.log(num.toString());//"1.2345678901234 568e+21" 看到这里大家难免会有些疑问,这些基本的数据类型的值都是常量,而常量是没有方法的,为什么能 够调用方法呢,答案是这样的,五种基本类型除了null、undefined以外都有与之对应的特殊的引 用类型——包装类型。当代码被解释执行时,底层会对基本类型做一个类型转换,即将基本类型转换 成引用类型,这样就可以调用相应引用类型有权访问到的方法。 二、toString()方法定义在何处, 运行以下代码: var pro = Object.prototype;var pr = pro.__proto__;//ie11之前版本不支 持该属性console.log(typeof pro);//"object"console.log(String(pro));//"[object Object]"console.log(pro.hasOwnProperty("toString"));//trueconsole.log (typeof pr);//"object"console.log(String(pr));//"null"console.log(pr.hasOwnPr operty("toString"));//报错 由此可知,toString()定义在Object.prototype上; 三、使用Object.prototype上的原生toString()方法判断数据类型,使用方法如下: Object.prototype.toString.call(value) 1.判断基本类型: Object.prototype.toString.call(null);//”[object Null]”Object.prototype.toString.call(undefined);//”[object Undefined]”Object.prototype.toString.call(“abc”);//”[object String]”Object.prototype.toString.call(123);//”[object Number]”Object.prototype.toString.call(true);//”[object Boolean]” 2.判断原生引用类型: 函数类型 Function fn(){console.log(“test”);}Object.prototype.toString.call(fn);//”[o bject Function]” 日期类型 var date = new Date();Object.prototype.toString.call(date);//”[object Date]” 数组类型 var arr = [1,2,3];Object.prototype.toString.call(arr);//”[object Array]” 正则表达式 var reg = /[hbc]at/gi;Object.prototype.toString.call(arr);//”[object Array]” 自定义类型 person = new Person("Rose", 18);Object.prototype.toString.call(arr); //”[object Object]” 很明显这种方法不能准确判断person是Person类的实例,而只能用instanceof 操作符来进行判断,如下所示: console.log(person instanceof Person);//输出结果为true 3.判断原生JSON对象: var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);console.log(isNativeJSON);//输出结果为”[object JSON]”说明JSON是原生的,否则不是; 注意:Object.prototype.toString()本身是允许被修改的,而我们目前所讨论的关于Object.prototype.toString()这个方法的应用都是假设toString()方法未被修改为前提的。 在JavaScript中,如何准确获取变量的类型名是一个经常使用的问题. 但是常常不能获取到变量的精确名称,或者必须使用jQuery 中的方法,这里 我通过 typeof ,jQuery.type 和 通过构造函数来获取变量类型 这三种方法详细介绍一遍. 希望可以对你提供帮助. 看到题目的第一眼,有些同学可能会想到 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或+"10", 如果没有转换成功,返回NaN,由于NaN 的一个 特性: NaN != NaN,故判断转换成功与否的常见做法: (这也是我参见 jQuery的源码发现 的,jQuery源码读100遍都不为过) , ("10x" - 0) == ("10x" - 0); // 结果为假! 使用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(www.visa158.com); }); 因为 Object.prototype.toString() 方法调用结果如下 var core_toString = {www.hunanwang.net}.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 + "]" ] = 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); 发现,这两个东西其实一个东西 但是,在某些情况下,需要这么写 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() 注意,这里已经不是熟悉 [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.log(p.constructor); 现在要做的事 : 如何将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] + '|'); 使用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使用构造函数获取变量的类型名】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索