老话题了,各种方案和相关讨论都不少,简单总结下:

悠久的typeof

JavaScript里只有五种基本数据类型:number, string, boolean, null, undefined. 其它的都是复合数据类型object.

值和数据类型是两码事。比如:null是null类型的唯一值,undefined是undefined类型的唯一值,就如true和false是boolean类型的唯两值一样。

可以用typeof检测出以下6种数据类型:number, string, boolean, undefined, object, function.

注意:typeof null == “object”. null类型的唯一值null的类型是object类型。(很拗口,但事实就是这样)

因此,对于五种基本数据类型来说,用下面的代码就可以检测出来:

// 获取变量o的数据类型
function type(o) {
    return (o === null) ? 'null' : typeof(o);
}

instanceof的作用typeof只能检测基本数据类型,对于复合数据类型,除了function,都通通返回'object'.

instanceof可以检测某个对象是不是另一个对象的实例,注意instanceof的右操作数必须为对象:

alert(1 instanceof Number); // false
alert({} instanceof Object); // true

instanceof还可以检测父类型:

function Animal() {};
function Pig() {};
Pig.prototype = new Animal();
alert(new Pig() instanceof Animal); // true

可以看出,instanceof不适合用来检测一个对象本身的类型。

救命稻草:constructor

JavaScript里的所有对象都拥有一个constructor属性,但JavaScript里并非一切都是对象:

alert(1.constructor); // 报错

var o = 1;
alert(o.constructor); // Number
o = null; // or undefined
alert(o.constructor); // 报错

alert({}.constructor); // Object
alert(true.constructor); // Boolean

可以看出,null和undefined没有constructor,number和string数据类型的字面量,也没有constructor,但number和string数据类型的变量有constructor(在寻找constructor属性时,会自动转换成Number或String对象)。

下面是Johg Resig《Pro JavaScript Techniques》书中的一张表:

这样,对于复合数据类型,我们可以采用下面的方法检测:

...
isArray: function(arr) {
   return !!arr && arr.constructor == Array;
}
...

jQuery 1.2中采用的就是上面的代码。

一切看起来很完美,然而不安分的iframe总喜欢来捣点鬼:

// 请在非ie浏览器中运行
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1, 2, 3); // [1,2,3]

alert(arr.constructor === Array); // false

原因很简单:不同frame中的Array拥有不同的constructor.

鸭子也上场:Duck Typing

在犀牛书里,提到一句老话:“如果走路像鸭子,叫声也像鸭子,那它就是一个鸭子!” 换言之,对于Array来说,如果一个对象有splice和join属性,那它就是Array. 这就是Duck Typing:

function isArray(o) {
    return o != null && typeof o === ‘object’ &&
           'splice' in o && 'join' in o;
}

上面是Prototype 1.6中的代码。

显然,鸭子检测很容易误把自造的天鹅也当成鸭:

alert(isArray({'splice': '', 'join': ''})); // true

鸭子检测的一个用途是,可以用来检测类似对象,比如类数组:

function isArrayLike(x) {
    if (x instanceof Array) return true; // Real arrays are array-like
    if (!('length' in x)) return false;  // Arrays must have a length property
    if (typeof x.length != 'number') return false;  // Length must be a number
    if (x.length < 0) return false;                 // and nonnegative
    if (x.length > 0) {
        // If the array is nonempty, it must at a minimum
        // have a property defined whose name is the number length-1
        if (!((x.length - 1) in x)) return false;
    }
    return true;
}

上面的代码摘自犀牛书。

时间太晚,今天就写到这。留两个问题:

  • constuctor示例中,var xArray = window.frames[window.frames.length-1].Array;能否写成var xArray = iframe.Array;?为什么?
  • JavaScript中,一切皆是对象。这句话究竟对不对?为什么?

晚安,朋友们!

[ 本帖最后由 lifesinger 于 2009-2-5 14:13 编辑 ]

 引用  报告 回复 顶部
lifesinger

爬虫
Rank: 2

UID 91925
精华 0
积分 62
帖子 13
威望 35
阅读权限 20
注册 2008-10-9
状态 在线

#2

大 中 小

使用道具  
发表于 2009-2-5 14:15  资料  个人空间  主页 短消息  加为好友 

回归简单:Object.toString

这个方法并不新奇,在犀牛书的 9.7 Determining Object Type 一节中,有详细的讨论,但一直没有引起注意(犀牛书太厚,仔细阅读过的人,在世界范围内看来都是凤毛麟角的)。直到老道(Douglas Crockford)的火星文出现:The Miller Device(号召大家都向老道学习,多挖掘有价值的火星知识):

Object.prototype.toString.apply(value) === '[object Array]'

ECMA-262中的解释:

Object.prototype.toString( )
When the toString method is called, the following steps are taken:
1. Get the [[Class]] property of this object.
2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.
3. Return Result (2)

这样,就有了:

function isArray(o) {
    return Object.prototype.toString.call(o) === '[object Array]';
}

因为是字符串比较,也就解决了跨iframe的问题。

结合typeof和toString方法,可以比较完美的实现对JavaScript基本类型和内置对象的探测了:

var _toS = Object.prototype.toString,
    _types = {
    'undefined' : 'undefined',
    'number' : 'number',
    'boolean' : 'boolean',
    'string' : 'string',
    '[object Function]' : 'function',
    '[object RegExp]' : 'regexp',
    '[object Array]' : 'array',
    '[object Date]' : 'date',
    '[object Error]' : 'error'
};

function type(o) {
    return _types[typeof o] || _types[_toS.call(o)] || (o ? 'object' : 'null');
}

详细测试页面请参考这里:typeof.js

自定义对象惹的祸

来看下面的代码:

function Animal() {}
function SubArray() {}
SubArray.prototype = [];

var toString = Object.prototype.toString;
alert(toString(new Animal()));
alert(toString(new SubArray()));
// firefox: [object Window]
// ie: [object Object]
// chrome: [object global]

alert(new SubArray() instanceof Array); // true
alert(new Animal() instanceof Animal); // true

可以看出,Object.toString方法,对于非内置对象来说,在各个浏览器下返回的值各异。

因此,如果要检测非内置对象,还是得用constructor和instaceof. 或者像Mootools一样,通过框架的机制来判断:

Mootools has an interesting approach with it’s $type function. Mootools wraps all native objects via the “Native” constructor in order to easily implement new methods for them. The Native constructor also creates a new property, called $family, which is the value returned by the $type() utility function.

好了,本文结束。JavaScript,每天精进一点点,乐哉!

参考资料

  • 文中提到的犀牛书指的是:OReilly.JavaScript.The.Definitive.Guide.5th.Edition.Aug.2006
  • How to write a robust ‘isArray’(很详细的介绍,一步一步,很有条理)
  • The Miller Device(老道的文章总是言简意赅,一针见血……)
  • getClass.js(toString方法检测Class的一个实现)
  • typeof增加版(很不错的实现方案)
  • toString in MDC(Mozilla是与时俱进的官方)

Tags:
JavaScript,
类型检测

JavaScript类型检测小结-http://bbs.51js.com/viewthread.php?tid=82661相关推荐

  1. http://bbs.winos.cn/viewthread.php?tid=1147extra=page=2

    http://bbs.winos.cn/viewthread.php?tid=1147&extra=&page=2 转载于:https://blog.51cto.com/215363/ ...

  2. LINUX新手入门及安装配置FAQ(http://bbs.blueidea.com/viewthread.php?tid=635906amp;page=)

    LINUX新手入门及安装配置FAQ 剑气凌人 [楼主] 尖脐 荣誉管理团队 帖子 6386  体力 10046   威望 168   当前 北京 海淀区 发短消息 个人网站 1# 大 中 小 发表于 ...

  3. JavaScript学习笔记:类型检测

    JavaScript学习笔记:类型检测 1.利用typeof检测数据类型 注意:type of null,返回的不是"null",而是"object".type ...

  4. 聊一聊JavaScript的类型检测

    JavaScript的类型检测 一共有四种原生办法检测js的类型 1. typeof 2. instanceof 3. constructor 4. Object.prototype.toString ...

  5. 说说javascript变量类型和变量类型检测

    为什么80%的码农都做不了架构师?>>>    javascript是一种弱类型语言,它的典型例子就是即变量在使用的时候可以给它赋值任何类型.那么先来看下javascript都有那些 ...

  6. JavaScript中类型检测

    文章首发: http://www.cnblogs.com/sprying/p/4349426.html 本文罗列了一般Js类型检测的方法,是构建Js知识体系的一小块,这篇文章是我很早之前总结的. 一. ...

  7. JavaScript基本数据类型及类型检测

    数据类型 原始值 Boolean String Number Null Undefined Symbol BigInt 引用数据类型 对象 < Object Function Date RegE ...

  8. javascript类型注意事项

    以下是javascript类型的注意事项: null:表示尚未存在的对象,注意,尽管尚未存在,也是个对象啊,所以用typeof检测一个null值变量的结果是Object:不过,为了便于写if语句,在j ...

  9. 【前端面试】数据类型与类型检测

    1.在JS中有哪些数据类型? (1)JavaScript中的数据类型有6种: 基础数据类型5种:Boolean.String.Number.undefined.null 复杂数据类型1种:Object ...

最新文章

  1. 有上下界网络流 ---- P4843 清理雪道(DAG图上最小路径重复边覆盖)【模板】有源汇上下界最小流
  2. CoordinatorLayout中AppBarLayout的折叠仅依靠滑动RecyclerView实现
  3. Packet tracer软件安装,模拟网络搭建【Packet tracer安装和使用】
  4. 2.1.2 操作系统之进程的状态(运行、就绪、阻塞、创建、终止)及转换(就绪-运行、运行-就绪、运行-阻塞、阻塞-就绪)
  5. 如何基于Weex实现创新交互体验?手淘开源技术BindingX案例解析
  6. JUnit4套件测试
  7. centos7邮件服务器SSL配置
  8. jQuery Mobile中网格grid样式ui-grid-*
  9. opencv4.3.0+Visual Studio 2019环境配置
  10. 【风马一族_Java】如何使用ACSLL表的值,
  11. 2021年下半年软考-网络工程师答案及解析(中级)
  12. Ubuntu可视化监控温度
  13. 【智衡跨境电商shopee运营】Shopee平台流量入口有哪些?
  14. 实验三 数字加法器的设计【Verilog】
  15. 工具使用分享之爱思助手安装苹果APP
  16. 7.网络基础配置实验报告(2)
  17. ECharts修改坐标轴,坐标轴字体,坐标轴网格样式
  18. 秦王扫六合,虎视何雄哉
  19. Git+Gitlab+Ansible剧本实现一键部署动态网站(二)--技术流ken
  20. java redis点赞_微信亿级在线点赞系统,用Redis如何实现?

热门文章

  1. 物联网在智慧农业中的应用
  2. 计算机一级操作题文档,计算机一级操作题集
  3. iOS11 和 iPhone X 的适配
  4. 嵌入式linux在windows,在Windows下启动Linux-嵌入式系统-与非网
  5. bat 批量复制 cd /d 报目录名或卷标语法不正确问题的解决
  6. 行业洞察 | 爱聊天的虚拟人
  7. 微信公众号中的视频下载
  8. 微信小程序录音上传php代码,小程序实现录音上传功能
  9. Python 理解使用requests库爬取数据
  10. 如何隐藏CAD布局视口线框?