zoukankan      html  css  js  c++  java
  • JavaScript数据类型判断的四种方法

    码文不易啊,转载请带上本文链接呀,感谢感谢 https://www.cnblogs.com/echoyya/p/14416375.html

    本文分享了JavaScript类型判断的四种方法:typeofinstanceofObject.prototype.toString.call()constructor

    JavaScript数据类型

    JavaScript有八种内置类型,除对象外,其他统称为基本类型

    • 空值(null)

    • 未定义(undefined)

    • 布尔值(boolean)

    • 数字(number)

    • 字符串(string)

    • 对象 (object)

    • 符号(symbol, ES6中新增)

    • 大整数(BigInt, ES2020 引入)

    Symbol: 是ES6中引入的一种原始数据类型,表示独一无二的值。

    BigInt:是 ES2020 引入的一种新的数据类型,用来解决 JavaScript中数字只能到 53 个二进制位(JavaScript 所有数字都保存成 64 位浮点数,大于这个范围的整数,无法精确表示的问题。具体可查看:新数据类型 — BigInt

    一、typeof

    typeof是一个操作符而不是函数,其右侧跟一个一元表达式,并返回这个表达式的数据类型。返回的结果用该类型的字符串(全小写字母)形式表示

    包括以下 8 种:string、number、boolean、undefined、function 、symbol、bigInt、object。

    对于数组,对象,null以及时间等数据,typeof只能返回object,而不能直接返回对应的类型,还需要通过其他法判断。

    console.log(typeof "");            // string
    console.log(typeof 1 );            // number
    console.log(typeof NaN );          // number
    console.log(typeof true);          // boolean
    console.log(typeof undefined);     // undefined
    console.log(typeof function(){});  // function
    console.log(typeof isNaN);         // function
    console.log(typeof Symbol());      // symbol
    console.log(typeof 123n);          // bigint
    console.log(typeof []);            // object
    console.log(typeof {});            // object
    console.log(typeof null);          // object
    console.log(typeof new Date());    // object
    console.log(typeof new RegExp());  // object
    

    二、instanceof

    instanceof 是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。 需特别注意:instanceof 检测的是原型

    即instanceof 用来比较一个对象是否为某一个构造函数的实例。instanceof可以准确的判断复杂数据类型,但是不能正确判断基本数据类型

    console.log(12 instanceof Number);                 // false
    console.log('22' instanceof String);               // false
    console.log(true instanceof Boolean);              // false
    console.log(null instanceof Object);               // false
    console.log(undefined instanceof Object);          // false
    console.log(function a() {} instanceof Function);  // true
    console.log([] instanceof Array);                  // true
    console.log({a: 1} instanceof Object);             // true
    console.log(new Date() instanceof Date);           // true
    

    2021/3/8 补充:
    instanceof 的原理:主要的实现原理就是只要右边变量的 prototype在左边变量的原型链上即可。
    因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果存在返回true 否则返回false

    function new_instance_of(leftVaule, rightVaule) { 
        let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
        leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
        while (true) {
        	if (leftVaule === null) {
                return false;	
            }
            if (leftVaule === rightProto) {
                return true;	
            } 
            leftVaule = leftVaule.__proto__ 
        }
    }
    

    注意:instanceof 运算时会递归查找leftVaule的原型链,即leftVaule.__proto__.__proto__.__proto__.__proto__... 直到找到了或者找到顶层为止。

    一句话理解其运算规则:instanceof 检测左侧的 __proto__ 原型链上,是否存在右侧的 prototype 原型。

    三、constructor

    1. JavaScript中,每个对象都有一个constructor属性,可以得知某个实例对象,到底是哪一个构造函数产生的, constructor属性表示原型对象与构造函数之间的关联关系。
    • 当一个函数F被定义时,JS引擎会为F添加prototype原型,然后在prototype上添加一个constructor属性,并让其指向F的引用,F利用原型对象的constructor属性引用了自身,当F作为构造函数创建对象时,原型上的constructor属性被遗传到了新创建的对象上,从原型链角度讲,构造函数F就是新对象的类型。这样做的意义是,让对象诞生以后,就具有可追溯的数据类型。

    • 通过typeof运算符来判断它是原始的值还是对象。如果是对象,就可以使用constructor属性来判断其类型。

    • 如判断数组的函数:

    function isArray(data){ 
      return typeof data == "object" && data.constructor == Array; 
    }
    isArray([])  // true
    

    注意:null 和 undefined 是没有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。

    console.log('22'.constructor === String)             // true
    console.log(true.constructor === Boolean)            // true
    console.log([].constructor === Array)                // true
    console.log(document.constructor === HTMLDocument)   // true
    console.log(window.constructor === Window)           // true
    console.log(new Number(22).constructor === Number)   // true
    console.log(new Function().constructor === Function) // true
    console.log(new Date().constructor === Date)         // true
    console.log(new RegExp().constructor === RegExp)     // true
    console.log(new Error().constructor === Error)       // true
    
    1. 如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错。所以,修改原型对象时,一般要同时修改constructor属性的指向。
    function Rectangle(width, height){
        this.width = width;
        this.height = height;
        this.getArea = function(){
            return '矩形的面积为' + (width * height);
        }
    }
     
    var rect1 = new Rectangle(40, 20);
    var rect2 = new Rectangle(50, 20);
    var rect3 = new Rectangle(60, 20);
    console.log(rect1.getArea());
    console.log(rect2.getArea());
    console.log(rect3.getArea());
    
    • 如上代码,每次实例化出一个对象,都会添加getArea方法,是三个对象共有且不变的,因此将getArea放在构造函数中就会在创建对象时被多次添加,浪费内存!

    • 因此我们将getArea添加到原型对象上就减少了多次添加实例化对象会沿着原型链查找到此属性

    • 实现了共享属性:

    function Rectangle(width, height){
        this.width = width;
        this.height = height;
    }
     
    // 直接替换原型对象,但是要记得添加上构造函数属性
    Rectangle.prototype = {
        constructor: Rectangle,
        getArea: function(){
            return '矩形的面积为' + (this.width * this.height);
        }
    }
     
    // 修改特性
    Object.defineProperties(Rectangle.prototype, {
        constructor: {
            enumerable: false,
            configurable: false,
            writable: false
        },
        getArea: {
            enumerable: false,
            configurable: false,
            writable: false
        }
    })
     
    var rect1 = new Rectangle(40, 20);
    var rect2 = new Rectangle(50, 20);
    var rect3 = new Rectangle(60, 20);
    console.log(rect1.getArea());
    console.log(rect2.getArea());
    console.log(rect3.getArea());
    
    1. 很多情况下,我们可以使用instanceof运算符或对象的constructor属性来检测对象是否为数组。如很多JS框架就是使用这两种方法来判断对象是否为数组类型。 但是检测在跨框架(cross-frame)页面中的数组时,会失败。原因就是在不同框架(iframe)中创建的数组不会相互共享其prototype属性。例如:
     <script>
         window.onload=function(){
             var iframe_arr=new window.frames[0].Array;
             console.log(iframe_arr instanceof Array);     // false
             console.log(iframe_arr.constructor == Array); // false
         }
     </script>
    

    四、Object.prototype.toString.call()

    • Object.prototype.toString(o)是 Object 的原型方法,

      1. 获取对象o的class属性。这是一个内部属性,

      2. 连接字符串:[object + 结果(1)],格式为 [object Xxx] ,其中 Xxx 就是对象的类型。

    • 对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。

      console.log(Object.prototype.toString.call(1))          // [object Number]
      console.log(Object.prototype.toString.call(1n))         // [object BigInt]
      console.log(Object.prototype.toString.call('123'))      // [object String]
      console.log(Object.prototype.toString.call(true))       // [object Boolean]
      console.log(Object.prototype.toString.call(undefined))  // [object Undefined]
      console.log(Object.prototype.toString.call(null))       // [object Null]
      console.log(Object.prototype.toString.call({}))         // [object Object]
      console.log(Object.prototype.toString.call([]))         // [object Array]
      console.log(Object.prototype.toString.call(function a() {}))  // [object Function]
      console.log(Object.prototype.toString.call(Symbol()))         // [object Symbol]
      console.log(Object.prototype.toString.call(Math))             // [object Math]
      console.log(Object.prototype.toString.call(JSON))             // [object JSON]
      console.log(Object.prototype.toString.call(new Date()))       // [object Date]
      console.log(Object.prototype.toString.call(new RegExp()))     // [object RegExp]
      console.log(Object.prototype.toString.call(new Error))        // [object Error]
      console.log(Object.prototype.toString.call(window)            // [object Window]
      console.log(Object.prototype.toString.call(document))         // [object HTMLDocument]
    
    • 封装一个准确判断数据类型的函数
      function __getType(object){
        return Object.prototype.toString.call(object).match(/^[objects(.*)]$/)[1];
      };
    
    • 可以解决上面的跨框架问题。
      <script>
          window.onload=function(){
              var iframe_arr=new window.frames[0].Array;
              console.log(Object.prototype.toString.call(iframe_arr)))  // "[object Array]"
          }
      </script>
    
    作者:Echoyya
    著作权归作者和博客园共有,商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    CentOS 7 安装Hadoop前的SSH免密码登录配置
    CentOS 7.1下SSH远程登录服务器详解-转
    Linux系统下如何配置SSH_Centos7 ssh连接配置 CentOS7下安全配置
    如何在CentOS 7上修改主机名
    【转】CentOS 6.3(x86_64)下安装Oracle 10g R2
    【转】CentOS 6.3(x86_32)下安装Oracle 10g R2
    【转】Linux Oracle服务启动&停止脚本与开机自启动
    Cacti在selinux开启的情况下使用
    Nagios在selinux开启的情况下使用
    Nagios状态长时间处于Pending的解决方法
  • 原文地址:https://www.cnblogs.com/echoyya/p/14416375.html
Copyright © 2011-2022 走看看