zoukankan      html  css  js  c++  java
  • JS 类型检测方法

    简介

    javascript的变量类型分为原始类型和引用类型。

    • 原始类型有6种, 注意多了 Symbol
      • Number
      • String
      • Boolean
      • Null
      • Undefined
      • Symbol
    • 引用类型包括
      • Function
      • Array
      • Date
      • Object
      • RegExp

    而检测这些类型的变量有3种办法:typeofinstanceofObject.prototype.toString.call。让我来一一例举,废话不多说,上代码。

    //首先是typeof
    var obj = 1;
    typeof obj; //"number"
    obj = "abc"
    typeof obj; //"string"
    obj = false
    typeof obj; //"boolean"
    obj = undefined;
    typeof obj; //"undefined"
    obj = null;
    typeof obj; //"object",WTF,其实这是js的一个bug,人艰不拆 T_T
    obj = Symbol();
    typeof obj; //"symbol"
    
    obj = function(){};
    typeof obj; //"function"
    obj = [];
    typeof obj; //"object"
    obj = {};
    typeof obj; //"object"
    obj = /w/g;
    typeof obj //"object"
    

    从上面我们可以得出type能检测原始类型number,string,boolean,undefined,引用类型的function。但是对于数组和对象却是无法区分。

    而关于引用类型,还可以尝试下instanceof操作符。

    var obj = function(){};
    obj instanceof Function; //true
    obj = [];
    obj instanceof Array; //true
    obj = {};
    obj instanceof Object; //true
    obj = new Date()
    obj instanceof Date; //true
    obj = /w/g;
    obj instanceof RegExp; //true
    //....wait for it, 事情其实还没完呢
    obj = [];
    obj instanceof Object; //true  所有引用类型其实都是继承自Object对象的,所以你懂的。
    

    incetanceof 操作符能鉴别引用类型,可惜有个缺憾是,如果想鉴别一个变量object类型而不是其他的functionarraydate什么的,仍然需要花一番力气。

    这里我们是不是漏了什么,如果..

    var obj = new String('abc');
    typeof obj; //"object" 。 
    obj instanceof String; //true 。 
    

    天了个撸,不能愉快玩耍了。要解释这个, 就得解释js里变量的赋值规则。

    • 原始类型的变量直接保存原始值,而不是一个指向对象的指针。如果一个变量赋值给另一个变量,那么每个变量都它自己的一份数据拷贝,并不会相互影响。
    • 引用类型的变量保存的是一个指向内存中实际对象所在的指针(或者说引用)。因此当你将一个对象赋值给变量时,实际是赋值给这个变量一个指针。意味着将一个变量赋值给另一个变量时,两个变量指向的是内存中同一个对象。
    var obj = 'abc';
    obj.something = 1;
    var firstChar = obj.charAt(0); //"a"
    console.log(obj.something); //undefined
    //实际上js做了这样的处理
    var obj = 'abc';
    var temp = new String(obj);
    var firstChar = temp.charAt(0); //"a"
    temp.something = 1;
    temp = null;
    console.log(obj.something); //undefined
    

    创建了一个临时的引用类型变量去访问属性,修改属性,然后就被释放了,扯远了。

    总而言之,如果指定obj = "abc"则obj保存的实际上就是abc的值,是一个基本类型。而如果指定obj = new String('abc')那么obj实际上保存的是一个指向字符串对象的指针。所以就不难理解两者对于typeofinstanceof的差别了
    额,读者:“说了这么多,你有没有一种万全的手段哇”。好吧, 我们来一个简单又粗暴的鉴别手段。

    var obj = 1;
    Object.prototype.toString.call(obj) === '[object Number]'; //true
    obj = new Number(1);
    Object.prototype.toString.call(obj) === '[object Number]'; //true
    obj = Symbol();
    Object.prototype.toString.call(obj) === '[object Symbol]'; //true
    
    obj = [];
    Object.prototype.toString.call(obj) === '[object Array]'; //true
    obj = new Array();
    Object.prototype.toString.call(obj) === '[object Array]'; //true
    Object.prototype.toString.call(obj) === '[object Object]'; //false
    

    这个方法是不是很好用呢, 哇哈哈哈哈。

    总结归纳了下,我列举了一些校验函数:

    //低版本ie中undefined变量可以被修改,所以使用void 0 获取真实的undefined值,
    var isUndefined = function(obj) {
        //or: return typeof obj === 'undefined';
        return obj === void 0;
    };
    //typeof null 的结果是"object"。
    var isNull = function(obj) {
        return obj === null;
    };
    // boolean值,number值和string值需要考虑两种情况,值为字面量时使用typeof和Object.prototype.toString能检测; 
    // 值为构造函数构建的时候需要使用Object.prototype.toString或者instanceof检测
    var isBoolean = function(obj) {
        return Object.prototype.toString.call(obj) == '[object Boolean]';
    };
    var isNumber = function(obj) {
        return Object.prototype.toString.call(obj) == '[object Number]';
    };
    var isString = function(obj) {
        return Object.prototype.toString.call(obj) == '[object String]';
    };
    var isSymbol = function(obj) {
        return Object.prototype.toString.call(obj) == '[object Symbol]';
    };
    var isNaN = function(obj) {
        return obj !== obj;
    };
    
    //typeof 操作符在引用类型的变量里能对function有效。
    var isFunction = function(obj) {
        //or:  return Object.prototype.toString.call(obj) == '[object Function]';
        return typeof obj === 'function';
    
    };
    var isDate = function(obj) {
        return Object.prototype.toString.call(obj) == '[object Date]';
    }
    var isArray = function(obj) {
        return Object.prototype.toString.call(obj) == '[object Array]';
    }
    var isObject = function(obj) {
        //or: return obj === Object(obj);
        return Object.prototype.toString.call(obj) == '[object Object]';
    }
    var isRegExp = function(obj) {
        //or: return obj === Object(obj);
        return Object.prototype.toString.call(obj) == '[object RegExp]';
    }
    
    var has = function(obj, key) {
        return Object.prototype.hasOwnProperty.call(obj, key);
    };
    //判断数组,字符串,对象是否为空
    var isEmpty = function(obj) {
        if (obj == null) return true;
        if (isArray(obj) || isString(obj)) return obj.length === 0;
        for (var key in obj) if (has(obj, key)) return false;
        return true;
    };
    

    最后再来一个好用的识别方法

    function getType(p) {
        if (obj === void 0) {
            return 'Undefined';
        }
        if (obj === null) {
            return 'Null';
        }
        /function.(w*)()/.test(p.constructor); //通过其构造函数来获取对应的类型。
        return RegExp.$1;
    }
    getType('1'); //"String"
    
  • 相关阅读:
    HDU2034:人见人爱A-B
    Codeup1085: 阶乘的和
    HDU2037:今年暑假不AC
    剑指Offer(Java版)第二十七题:从上往下打印出二叉树的每个节点,同层节点从左至右打印。
    剑指Offer(Java版)第二十六题:输入两个整数序列,第一个序列表示栈的压入顺序, 请判断第二个序列是否为该栈的弹出顺序。 假设压入栈的所有数字均不相等。 例如序列1、2、3、4、5是某栈的压栈序列, 序列5、4、3、2、1是该压栈序列对应的一个弹出序列, 但4、3、5、1、2就不可能是该压栈序列的弹出序列。
    剑指Offer(Java版)第二十五题:包含min函数的栈
    剑指Offer(Java版)第二十四题:顺时针打印矩阵
    MongoDB学习笔记10——分片
    MongoDB学习笔记9——复制
    MongoDB学习笔记8——优化
  • 原文地址:https://www.cnblogs.com/everlose/p/12501043.html
Copyright © 2011-2022 走看看