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 相关文章推荐
推荐17个优美新鲜的jQuery的工具提示插件
Sep 14 Javascript
javascript date格式化示例
Sep 25 Javascript
在linux中使用包管理器安装node.js
Mar 13 Javascript
用jQuery实现圆点图片轮播效果
Mar 19 Javascript
Angularjs 动态添加指令并绑定事件的方法
Apr 13 Javascript
Vue2.0学习之详解Vue 组件及父子组件通信
Dec 12 Javascript
js运算符的一些特殊用法
Jul 29 Javascript
浅谈webpack+react多页面开发终极架构
Nov 11 Javascript
详解一个基于react+webpack的多页面应用配置
Jan 21 Javascript
微信小程序自定义头部导航栏和导航栏背景图片 navigationStyle问题
Jul 26 Javascript
Vue实现图片轮播组件思路及实例解析
May 11 Javascript
Javascript Symbol原理及使用方法解析
Oct 22 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以mysqli方式连接类完整代码实例
2014/07/15 PHP
php以post形式发送xml的方法
2014/11/04 PHP
php中base_convert()进制数字转换函数实例
2014/11/20 PHP
使用PHP如何实现高效安全的ftp服务器(一)
2015/12/20 PHP
PHP基于mcript扩展实现对称加密功能示例
2019/02/21 PHP
解决Laravel5.2 Auth认证退出失效的问题
2019/10/14 PHP
jquery插件之easing使用
2010/08/19 Javascript
js 实现css风格选择器(压缩后2KB)
2012/01/12 Javascript
jquery改变disabled的boolean状态的三种方法
2013/12/13 Javascript
将数字转换成大写的人民币表达式的js函数
2014/09/21 Javascript
JavaScript中模拟实现jsonp
2015/06/19 Javascript
jQuery的文档处理程序详解
2016/05/10 Javascript
js放大镜放大购物图片效果
2017/01/18 Javascript
JavaScript中最常见的三个面试题解析
2017/03/04 Javascript
Node.js使用NodeMailer发送邮件实例代码
2017/03/06 Javascript
vue中路由参数传递可能会遇到的坑
2017/12/07 Javascript
在AngularJs中设置请求头信息(headers)的方法及不同方法的比较
2018/09/04 Javascript
Emberjs 通过 axios 下载文件的方法
2019/09/03 Javascript
详解利用eventemitter2实现Vue组件通信
2019/11/04 Javascript
微信小程序之导航滑块视图容器功能的实现代码(简单两步)
2020/06/19 Javascript
JavaScript实时更新当前的时间的示例代码
2020/07/15 Javascript
Python读取图片属性信息的实现方法
2016/09/11 Python
Python读取sqlite数据库文件的方法分析
2017/08/07 Python
Python字符串内置函数功能与用法总结
2019/04/16 Python
详解python编译器和解释器的区别
2019/06/24 Python
Python解析json代码实例解析
2019/11/25 Python
请说出你所知道的线程同步的方法
2013/04/19 面试题
C#实现对任一张表的数据进行增,删,改,查要求,运用Webservice,体现出三层架构
2014/07/11 面试题
韩语专业本科生求职信
2013/10/01 职场文书
基层工作经历证明
2014/01/13 职场文书
大学生职业生涯规划书范文
2014/01/14 职场文书
2015年五四青年节演讲稿
2015/03/18 职场文书
2015年乡镇民政工作总结
2015/05/13 职场文书
用python自动生成日历
2021/04/24 Python
Python中的套接字编程是什么?
2021/06/21 Python
Spring Data JPA框架自定义Repository接口
2022/04/28 Java/Android