资讯专栏INFORMATION COLUMN

JavaScript的类型检测

arashicage / 1788人阅读

摘要:类型检测在中提供两种检测类型的方法,但是它们并不总是靠谱。引用类型引用类型使用检测,返回都是。这个时候可以用,它的语法是实例对象构造函数不仅能检测构造对象的构造器,还检测原型链。

类型检测

在js中提供两种检测类型的方法,但是它们并不总是靠谱。

typeof

instanceof

下面我们来看看各个类型的应该如何进行检测比较靠谱

1. 基本类型

基本类型(除null之外)的检测使用typeof,它的语法很简单

var number = 1,
    string = "s",
    boolean = true,
    un = undefined,

typeof number; // "number"
typeof string; // "string"
typeof boolean;// "boolean"
typeof un; // "undefined"
1.2 null

如果我们使用typeof来检测,结果会是

var n = null;
typeof n;//"object"

有人说这是个bug,有人说这是因为null本身就代表着一个空对象,我们也经常用null来解除引用。不管怎么说,我们可以这样检测null

var n = null;
function isNull(n){
    if(!n && typeof n !== "undefined"){
        return true;
    }
    return false;
}
isNull(n);// true
1.3 非数字

判断一个变量是否是数字,可以使用isNaN(),这个方法的意思是is not a numher,也就是说返回true的时候说明变量不是一个数字。

var a = 1,
    b = "s",
    c = "1";
isNaN(a); // false
isNaN(b); // true
isNaN(c); // true
2. 引用类型

引用类型使用typeof检测,返回都是"object"。这其实没什么意义,我们要知道的是变量具体是哪个引用类型的,例如数组,自定义的类型等等。这个时候可以用instanceof,它的语法是

实例 instanceof 对象构造函数

var arr = [];
arr instanceof Array; // true
function Person(){};
var p = new Person();
p instanceof Person; // true

instanceof不仅能检测构造对象的构造器,还检测原型链。

var now = new Date();
now instanceof Date; // true
now instanceof Object; // true
2.1 数组检测

数组在编程中相当常见,在框架中也是,如何准确地检测数组类型,是相当重要的。

可能有人会说了,使用instanceof不就可以了。非也。在js中,有一个很古老的跨域问题:在iframe之间来回传递数组,而instanceof不能跨帧。

什么叫不能跨帧?假设在一个浏览器的帧(frame A)里的一个对象传入到另外一个帧(frame B)中,两个帧都定义了一个构造函数Person,如果来自帧A的对象是帧APerson的实例,则

frameAPersonInstance instanceof frameAPerson; //true

frameAPersonInstance instanceof frameBPerson; //false

那怎么办?

首先,有人提出了使用duck typing的思路来解决这个问题,duck typing的意思就是:像鸭子一样走路、游泳并且嘎嘎叫的就是鸭子,这是个很有意思的想法,它的本质就是我们关注对象能做什么,不是关注对象是什么,采用这样的思路,我们检测对象实例是否有sort属性来判断对象实例是否是一个数组,具体实现如下

function isArray(value) {
    return typeof value.sort === "function";
}

之后,kangax发现了一个很有趣的现象,调用某个值的内置toString()方法在所有浏览器中都返回标准的字符串结果,对于数组来说,返回的字符串为"[object Array]",这个方法对识别内置对象都非常有效,因此jq也是采取了这种方式来实现的isArray()的方法。

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

之后,ECMA5将Array.isArray()正式引入JavaScript,提供了一个能准确检测一个变量是否为数组类型的

Array.isArray(variable);
3. 最后

到这里,你以为已经解决了所有的类型检测问题了吗?并不是。在《JavaScript框架设计》这本书中,详细地谈论各种类型检测的兼容性问题,并且在massframework给出了一个很不错的实现,从代码里面来学习可以学到更多。

// 建立类型的映射
var class2type = {
    "[objectHTMLDocument]"       : "Document",
    "[objectHTMLCollection]"     : "NodeList",
    "[objectStaticNodeList]"     : "NodeList",
    "[objectIXMLDOMNodeList]"    : "NodeList",
    "[objectDOMWindow]"          : "Window",
    "[object global]"            : "Window", //safari 4.04
    "null"                       : "null",
    "NaN"                        : "NaN",
    "undefined"                  : "undefined"
};

// 正常情况下的类型
"Boolean,Number,String,Function,Array,Date,RegExp,Window,Document,Arguments,NodeList"
    .replace(/[^, ]/g, function(name) {
        class2type["[object " + name + "]"] = name;
    });

var toString = class2type.toString;

mass.type = function(obj,str){
    var result = class2type[ (obj == null || obj !== obj) ? obj : toString.call(obj) ]
                    || obj.nodeName || "#";

    if(result.charAt(0) === "#" ){  //兼容旧版浏览器与处理个别情况,如window.opera

        //hack,利用IE6,IE7,IE8 window == document 为 true,document == window 为 false的特性
        if(obj == obj.document && obj.document != obj){
            result = "Window";
        } else if (obj.nodeType === 9){ //nodeType 属性返回以数字值返回指定节点的节点类型。9代表document
            result = "Document";
        } else if (obj.callee){ //arguments 特有的属性
            resutl = "Arguments";
        } else if (isFinite(obj.length) && obj.item){ //obj.item()方法,可返回节点列表中处于指定的索引号的节点。
            result = "NodeList";
        } else {
            result = toString.call(obj).slice(8,-1); //[object XXXX]
        }

    }

    //提供一个进行类型比较的功能
    if(str){ 
        return str === result;
    }
    return result;
}
4. 参考

《编写可维护的JavaScript》

《JavaScript框架设计》

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87855.html

相关文章

  • JavaScript检测原始值、引用值、属性

    摘要:检测函数从技术上讲,中的函数是引用类型,同样存在构造函数,每个函数都是其实例,比如不好的写法然而,这个方法亦不能跨帧使用,因为每个帧都有各自的构造函数,好在运算符也是可以用于函数的,返回。 上周写过一篇读书笔记《编写可维护的JavaScript》之编程实践,其中 第8章 避免『空比较』是博主在工作中遇坑较多的雷区,所以特此把该章节重新整理分享,希望大家不再坑队友(>﹏<)。 在 Jav...

    刘德刚 评论0 收藏0
  • JavaScript数据类型及其检测

    摘要:中的数据类型及其检测数据类型基本类型引用类型类型检测只能检测基本数据类型,对于还有一个用于检测某个对象的原型链是否包含某个构造函数的属性适用于检测对象,它是基于原型链运作的属性返回一个指向创建了该对象原型的函数引用,该属性的值是哪个函数本身 JavaScript中的数据类型及其检测 1. 数据类型 1.1 基本类型 Number String Boolean Null Undefin...

    Bryan 评论0 收藏0
  • JavaScript类型检测详解

    摘要:种原始类型对象属性种原始类型中种原始类型为,,,,发现除外的其他种基本类型均可以用来识别因为会得到,所以直接用来检测对象的对象包括内置对象,,等和自定义对象。其他检测方法,都各有缺陷,不能精确。属性检测属性是否在实例对象中应该用。 本篇介绍一下如何检测JavaScript各种类型。 • 5种原始类型• 对象• Function• Array• 属性 5种原...

    张金宝 评论0 收藏0
  • javascript基础篇:JS中数据类型检测专题

    摘要:用来检测数据类型的运算符语法虽然是基本数据类型值,但是它属于空对象指针,检测的结果是对象使用有自己的局限性,不能具体细分当前的值是数组还是正则也就是不能细分对象类型的值先算检测某一个实例是否属于某各类的实例构造函数使用检测某个值是否属于某 typeof 用来检测数据类型的运算符语法:typeof[value] typeof 12 //=>number typeof NaN //=>nu...

    Honwhy 评论0 收藏0
  • javascript中对变量类型判断

    摘要:当需要变量是否是类型时,可以使用进行判断。本来是原型对象上的属性,指向构造函数。不过使用也不是保险的,因为属性是可以被修改的,会导致检测出的结果不正确,例如在上面的例子中,原型中的被修改为指向到,导致检测不出实例对象真实的构造函数。 在JavaScript中,有5种基本数据类型和1种复杂数据类型,基本数据类型有:Undefined, Null, Boolean, Number和Stri...

    entner 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<