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]"
  • 相关阅读:
    DGA域名可以是色情网站域名
    使用cloudflare加速你的网站隐藏你的网站IP
    167. Two Sum II
    leetcode 563. Binary Tree Tilt
    python 多线程
    leetcode 404. Sum of Left Leaves
    leetcode 100. Same Tree
    leetcode 383. Ransom Note
    leetcode 122. Best Time to Buy and Sell Stock II
    天津Uber优步司机奖励政策(12月28日到12月29日)
  • 原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/10486016.html
Copyright © 2011-2022 走看看