JavaScript数据类型判定的总结笔记


Posted in Javascript onJuly 31, 2015

用typeof 来检测数据类型
Javascript自带两套类型:基本数据类型(undefined,string,null,boolean,function,object)和对象类型。

但是如果尝试用typeof 来检测对象类型都一律返回"object"并不能加以区分

typeof null // "object"
typeof []  // "object"
typeof document.childNodes //"object"
typeof /\d/ //"object"
typeof new Number() //"object"

用constructor 属性来检测类型的构造函数

[].constructor === Array  //true
document.childNodes === NodeList  //true
/\d/.constructor === RegExp   //true
 
function isRegExp(obj) {
  return obj && typeof obj === "object" && obj.constructor === RegExp;
} //检测正则表达式对象
 
function isNull(obj){
  return obj === null;
}

用construct检测可以完成大多数的类型检测,null特殊直接比较。然而iframe中的数组类型确无法检测出正确类型,这是用construct检测的一个缺陷;同时在旧版本IE下DOM和BOM的construct是无法访问的

利用 Object.prototype.toString 来判断

Object.prototype.toString.call([]) //"[object Array]"
Object.prototype.toString.call(/\d/) // "[object RegExp]"
Object.prototype.toString.call(1)//"[object Number]"

来看看jQuery源码中是如何使用toString方法的

/*
* jQuery JavaScript Library v1.11.2
*/
var class2type = {};  //用来保存js数据类型
 
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {//构造class2type存储常用类型的映射关系,遍历基本类型并赋值,键值为 [object 类型]
 class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
type: function( obj ) {
  if ( obj == null ) {//首先如果是null则返回null字符串
   return obj + "";
  }
//接着判断给定参数类型是否为object或者function,是的话在映射表中寻找 toString后的键值名称并返回,不是的话利用typeof就可以得到正确类型。
  return typeof obj === "object" || typeof obj === "function" ?
   class2type[ toString.call(obj) ] || "object" :
   typeof obj;
 },
/****************************/ 
jQuery.type(/\d/)  //"regexp"
jQuery.type(new Number())  //"number"

这里能够使用toString方法来检测是因为不同对象都会重新定义自己的toString方法

说说一些特殊类型的检测

JavaScript数据类型判定的总结笔记

上述调试是在IE8中进行的,因为undefined 在javascript中并不是关键字,在IE8以下(之后的版本不可以赋值)是可以赋值的,查看jQuery.type源码可知,对于 undefined检测由是 typeof undefined完成的。jQuery.type并不能在旧的IE中检测出undefined的正确性。想要获得纯净的undefined可以使用 void 0

JavaScript数据类型判定的总结笔记

另外,对于DOM,BOM对象在旧的IE中使用Objec.prototype.toString检测出来的值均为 “[object Object]”

JavaScript数据类型判定的总结笔记

但是在chrome下的结果却完全不同(chrome可以检测出真实类型)

JavaScript数据类型判定的总结笔记

了解一下jQuery检测特殊类型

isWindow: function( obj ) {//ECMA规定window为全局对象global,且global.window === global
 return obj != null && obj == obj.window;
},
isPlainObject: function( obj ) {
 var key;
 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
  return false;
 }
 try {//判断它最近的原形对象是否含有isPrototypeOf属性
  if ( obj.constructor &&
   !hasOwn.call(obj, "constructor") &&
   !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
   return false;
  }
 } catch ( e ) {
  return false;
 }
 if ( support.ownLast ) {
  for ( key in obj ) {
   return hasOwn.call( obj, key );
  }
 }

mass Framework相对jQuery中改善的地方

var class2type = {//将可能出现的类型都映射在了class2type对象中,从而减少isXXX函数
  "[object HTMLDocument]": "Document",
  "[object HTMLCollection]": "NodeList",
  "[object StaticNodeList]": "NodeList",
  "[object DOMWindow]": "Window",
  "[object global]": "Window",
  "null": "Null",
  "NaN": "NaN",
  "undefined": "Undefined"
 };
type: function(obj, str) {
   var result = class2type[(obj == null || obj !== obj) ? obj : serialize.call(obj)] || obj.nodeName || "#"; //serialize == class2type.toString
   if (result.charAt(0) === "#") { //兼容旧式浏览器与处理个别情况,如window.opera
    //利用IE678 window == document为true,document == window竟然为false的神奇特性
    if (obj == obj.document && obj.document != obj) {//对DOM,BOM对象采用nodeType(单一)和item(节点集合)进行判断
     result = "Window"; //返回构造器名字
    } else if (obj.nodeType === 9) {
     result = "Document"; //返回构造器名字
    } else if (obj.callee) {
     result = "Arguments"; //返回构造器名字
    } else if (isFinite(obj.length) && obj.item) {
     result = "NodeList"; //处理节点集合
    } else {
     result = serialize.call(obj).slice(8, -1);
    }
   }
   if (str) {
    return str === result;
   }
   return result;
  }

类数组

类数组是一类特殊的数据类型存在,他们本身类似Array但是又不能使用Array的方法,他们有一个明显的特点就是含有length属性,而且 键值是以整数有序的排列的。这样的数组可以通过 Array.slice() 这样的方法转换成真正的数组,从而使用Array提供的方法。

常见类数组:arguments,document.forms,document.getElementsByClassName(等一些列节点集合NodeList,HTMLCollection),或者是一些特殊对象,如下所示:

var arrayLike={ 
   0:"a", 
   1:"b", 
   2:"c", 
   length:3 
}

通常情况下通过Array.slice.call既可以转换类数组,但是旧IE的HTMLCollection,NodeList不是Object 的子类,不能使用该方法,这时候需要构建一个空数组,然后将遍历节点push就如空数组中,返回新生成的数组即可,同时要区别出window 和 string对象,因为这类的对象同样含有length>=0(length不可被修改),但是不是类数组。

jQuery如何处理类数组的

makeArray: function( arr, results ) {
 var ret = results || [];
 if ( arr != null ) {
  if ( isArraylike( Object(arr) ) ) {
   jQuery.merge( ret,
    typeof arr === "string" ?
    [ arr ] : arr
   );  //jQuery.merge 合并数组 ,若是字符串则封装成数组河滨,不是则世界合并
  } else {
   push.call( ret, arr );
  }
 }
 return ret;
}

Ext.js是如何处理类数组的

toArray: function(iterable, start, end) {
    if (!iterable || !iterable.length) {
     return [];  //非类数组类型直接返回[]
    }
    if (typeof iterable === 'string') {
     iterable = iterable.split('');  //分解字符串
    }
    if (supportsSliceOnNodeList) {
     return slice.call(iterable, start || 0, end || iterable.length); //对于NodeList支持
    }
    var array = [],
     i;
    start = start || 0;
    end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
    for (i = start; i < end; i++) {
     array.push(iterable[i]);
    }
    return array;
   }

mass Framework.js是如何处理类数组的

slice: W3C ? function(nodes, start, end) { //var W3C = DOC.dispatchEvent; IE9开始支持W3C的事件模型
 return factorys.slice.call(nodes, start, end);
} : function(nodes, start, end) {
 var ret = [],
   n = nodes.length;
 if (end === void 0 || typeof end === "number" && isFinite(end)) {
  start = parseInt(start, 10) || 0;
  end = end == void 0 ? n : parseInt(end, 10);
  if (start < 0) {
   start += n;
  }
  if (end > n) {
   end = n;
  }
  if (end < 0) {
   end += n;
  }
  for (var i = start; i < end; ++i) {
   ret[i - start] = nodes[i];
  }
 }
 return ret;

以上就是本文的全部内容,希望对大家的学习有所帮助

Javascript 相关文章推荐
window.onbeforeunload方法在IE下无法正常工作的解决办法
Jan 23 Javascript
JS获取并操作iframe中元素的方法
Mar 21 Javascript
js使用html()或text()方法获取设置p标签的显示的值
Aug 01 Javascript
js实现类似新浪微博首页内容渐显效果的方法
Apr 10 Javascript
JS实现的文字与图片定时切换效果代码
Oct 06 Javascript
基于JS实现textarea中获取动态剩余字数的方法
May 25 Javascript
深入分析javascript中的错误处理机制
Jul 17 Javascript
ReactNative页面跳转Navigator实现的示例代码
Aug 02 Javascript
基于vue.js实现的分页
Mar 13 Javascript
JS与jQuery判断文本框还剩多少字符可以输入的方法
Sep 01 jQuery
vuex actions异步修改状态的实例详解
Nov 06 Javascript
使用JS来动态操作css的几种方法
Dec 18 Javascript
jquery代码实现多选、不同分享功能
Jul 31 #Javascript
Jquery实现瀑布流布局(备有详细注释)
Jul 31 #Javascript
jquery实现仿JqueryUi可拖动的DIV实例
Jul 31 #Javascript
jQuery+css3实现文字跟随鼠标的上下抖动
Jul 31 #Javascript
JavaScript实现图片轮播的方法
Jul 31 #Javascript
基于bootstrap3和jquery的分页插件
Jul 31 #Javascript
jquery-tips悬浮提示插件分享
Jul 31 #Javascript
You might like
php 文件缓存函数
2011/10/08 PHP
php生成gif动画的方法
2015/11/05 PHP
PHP验证类的封装与使用方法详解
2019/01/10 PHP
php 多继承的几种常见实现方法示例
2019/11/18 PHP
50个优秀经典PHP算法大集合 附源码
2020/08/26 PHP
网页里控制图片大小的相关代码
2006/06/25 Javascript
js实现上传图片之上传前预览图片
2013/03/25 Javascript
如何利用JS通过身份证号获取当事人的生日、年龄、性别
2016/01/22 Javascript
jQuery防止重复绑定事件的解决方法
2016/05/14 Javascript
详谈jQuery unbind 删除绑定事件 / 移除标签方法
2017/03/02 Javascript
4个顶级JavaScript高级文本编辑器
2018/10/10 Javascript
JS实现判断有效的数独算法示例
2019/02/25 Javascript
使用pm2部署node生产环境的方法步骤
2019/03/09 Javascript
详解在Javascript中进行面向切面编程
2019/04/28 Javascript
layer.open提交子页面的form和layedit文本编辑内容的方法
2019/09/27 Javascript
解决vue刷新页面以后丢失store的数据问题
2020/08/11 Javascript
vue.js封装switch开关组件的操作
2020/10/26 Javascript
JavaScript实现消消乐的源代码
2021/01/12 Javascript
python去除所有html标签的方法
2015/05/05 Python
详解Python中用于计算指数的exp()方法
2015/05/14 Python
利用Python自动监控网站并发送邮件告警的方法
2016/08/24 Python
简述:我为什么选择Python而不是Matlab和R语言
2017/11/14 Python
解决django服务器重启端口被占用的问题
2019/07/26 Python
pytorch中的weight-initilzation用法
2020/06/24 Python
python实现npy格式文件转换为txt文件操作
2020/07/01 Python
pycharm导入源码的具体步骤
2020/08/04 Python
pycharm 多行批量缩进和反向缩进快捷键介绍
2021/01/15 Python
python3定位并识别图片验证码实现自动登录功能
2021/01/29 Python
详解python第三方库的安装、PyInstaller库、random库
2021/03/03 Python
在html页面中取得session中的值的方法
2020/08/11 HTML / CSS
柯基袜:Corgi Socks
2017/01/26 全球购物
英文自荐信
2013/12/19 职场文书
小学新学期寄语
2014/04/02 职场文书
医德医风演讲稿
2014/05/20 职场文书
专职安全员岗位职责
2015/04/11 职场文书
2015年小学语文教师工作总结
2015/10/23 职场文书