zoukankan      html  css  js  c++  java
  • 类型和原生函数及类型转换(二:终结js类型判断)

    • typeof
    • instanceof
    • isArray()
    • Object.prototype.toString.call()
    • DOM对象与DOM集合对象的类型判断

     一、typeof

    typeof是一个一元运算符,放在任意类型的运算数前,这个运算返回的是字符串,该字符串说明的是运算数的类型。

    在原始值类型中除了null都能正确的返回对应的类型字符串名称,即:number、string、boolean、undefined可以正确判断类型。typeof null ==> object。

    但是需要注意的typeof NaN 是 number,除了正常的数值以外,还有Number.MAX_VALUE、Number.MIN_VALUE、Number.NaN、Number.POSITIVE_INFINITY、Number.NEGATIVE_INFINITY都是返回number。(NaN在类型上本身就属于数字的一种,其他特别的数值那也肯定是数值)

    在引用值类型中Function返回的是function,但是Array却又返回的是object。

    其余的引用值类型都是返回object。

    注意:typeof(obj)判断的obj如果未定的话也不会报错,而是返回“undefined”。

    ---------------------------------------------------------------------------------------------------

    懒人理解区:

    (简析:number,string,boolean,object,undefined,object,function可以正确的获取对应的类型字符串值,typeof遇到数组,对象,null都是返回object。)

     二、instanceof

     instanceof的内部机制是通过判断对象的原型链中是否能不能找到类型的prototype(原型)。在原型链上能找到对应的原型就会返回true。

    1 instanceof Number // false
    new Number(1) instanceof Number// true
    {} instanceof Object // 会报错,这是语法错误,这里的{}并不表示对象
    var a = {}
    a instanceof Object // true
    null instanceof Object // false
    [] instanceof Array // true

    那是不是就就可以用instanceof配合typeof来完成数组的判断呢?别急看一下代码:

    1 var iframe = document.createElement('iframe');
    2 document.body.appendChild(iframe);
    3 xArray = window.frames[window.frames.length-1].Array;
    4 var arr = new xArray(1,2,3,4,5);
    5 //这个写法IE下不支持,标准浏览器firefox,chrome下可以实现
    6 console.log(arr);//打印出:[1,2,3,4,5]
    7 console.log(arr instanceof Array);//false
    8 console.log(arr.constructor === Array);//false

    跨框架iframe的时候使用页面中的数组时,会失败,因为在不同的框架iframe中,创建的数组是不会相互共享其prototype属性的。类似将外层Array原型直接克隆到自己的内部window上,而instanceof的内部是基于原型链来判断,所以就没法判断了。

     三、isArray()

    用来判断对象是否是数组,是ES5标准的方法,在低版本的浏览器上不兼容。

    Array.isArray(obj)

    这个方法用来做类型判断的意义不大,除非做一些纯粹的移动端web开发或者确定只兼容ES5标准的浏览器项目。

     四、Object.prototype.toString.call()

     这个方法的使用我在上一篇博客:类型和原生函数及类型转换(一)末尾做了详细介绍,就不在这里赘述了,不是很了解的话可以到上一篇博客详细了解,这篇博客我主要就实现原理剖析。

    在ES5.1中,除了规范写的更详细一些以外,Object.prototype.toString方法和[[class]]内部属性的定义上也有一些变化,Object.prototype.toString方法的规范如下:

    15.2.4.2 Object.prototype.toString ( )

    toString方法被调用时,会执行下面的操作步骤:

    1. 如果this的值为undefined,则返回"[object Undefined]".
    2. 如果this的值为null,则返回"[object Null]".
    3. O成为调用ToObject(this)的结果.
    4. class成为O的内部属性[[Class]]的值.
    5. 返回三个字符串"[object ", class, 以及 "]"连接后的新字符串.

    如果你对JavaScript的值类型有所了解就知道,undefined和null没有包装类(在我上一篇博客中有介绍),如果要将这两个值类型的变量作为对象来使用在代码中会报错(这里涉及到了隐式类型转换),在ES3中这两个值类型的变量就没办法使用Object.prototype.toString.call()这种方式来实现类型判断(ES3中没有对这两个值类型的变量做特殊处理)。

    所有内置对象的[[Class]]属性的值是由本规范定义的.所有宿主对象的[[Class]]属性的值可以是除了"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String"之外的的任何字符串.[[Class]]内部属性是引擎内部用来判断一个对象属于哪种类型的值的.需要注意的是,除了通过Object.prototype.toString方法之外,本规范没有提供任何其他方式来让程序访问该属性的值(查看 15.2.4.2)

    最后来一个兼容的ES5的类型判断方法,ES6中的Object.prototype.toString.call()有些改变,是因为[[class]]内部属性没有,取而代之的是另外一个内部属性[[NativeBrand]].[[NativeBrand]]属性,但是toString方法的实现逻辑依然没有差别,后期在ES6部分我再将对应的兼容方法写出来。

     1 function myTypeof(value){
     2     var result = NaN;
     3     var valOf = typeof value;
     4     var inOf = value instanceof String || value instanceof Number || value instanceof Boolean;
     5     var typeObj = {
     6         "[object Object]":"object",
     7         "[object Array]":"array",
     8         "[object Function]":"function",
     9         "[object Date]":"date",
    10         "[object Error]":"error",
    11         "[object JSON]":"json",
    12         "[object Math]":"math",
    13         "[object RegExp]":"regExp",
    14         "[object Boolean]":"boolean",
    15         "[object String]":"string",
    16         "[object Number]":"number",
    17         "[object Undefined]":"undefined",
    18         "[object Null]":"null"
    19     }
    20 
    21     var str = Object.prototype.toString.call(value);
    22     for(var i in typeObj){
    23         if(i == str){
    24             result = typeObj[i];
    25             break;
    26         }
    27     }
    28     if( result === "number" && isNaN(value)){ //此处可以考虑 value === "NaN"这种情况
    29         return NaN;
    30     }
    31     if( inOf && valOf === "object"){
    32         return result + "-Object";
    33     }
    34     return result;
    35 }

     五、DOM对象与DOM集合对象的类型判断

    1 <div class="demo"></div>
    2 //js
    3 var do = document.getElementsByClassName("demo");
    4 Object.prototype.toString.call(do);//"[object HTMLCollection]"
    5 Object.prototype.toString.call(document);//"[object HTMLDocument]"
  • 相关阅读:
    mysql-5-aggregation
    mysql-4-functions
    mysql-3-orderby
    技术之心 | 云信和TA们携手打响防疫战
    疫情下的传统商企自救|4个Tips搭建销量过亿直播间
    那些2019年会爆发的泛娱乐黑科技风口
    流量难、获客难、增长难?增长黑客思维“解救”B端业务
    【翻译】Facebook全面推出Watch Party,可多人线上同看直播视频
    深入浅出聊一聊Docker
    C++写日志方法调试
  • 原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/10486016.html
Copyright © 2011-2022 走看看