JavaScript的范例检测

范例检测

在js中供应两种检测范例的要领,然则它们并不老是靠谱。

  1. typeof

  2. 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. 参考

  1. 《编写可保护的JavaScript》

  2. 《JavaScript框架设想》

    原文作者:zhangguixu
    原文地址: https://segmentfault.com/a/1190000006559542
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞