js中判断数据类型的4种方法

js中数据类型有8种:

基本数据类型(原始数据类型)(6种):

 number, string, boolean,null, undefined, symbol(es6新增)

引用数据类型:

 object, function

 

1. 最常用方法 -- typeof

缺点: 不能细分对象,数组,时间对象

 typeof 运算符的最终结果有7(typeof null === 'object')

   "number" //   typeof 123 ; typeof NaN
   "string"    //   typeof "123"
   "boolean" //  typeof  true
   "function" //  function f() {}; typeof f
   "object"    //  typeof {}; typeof [];typeof new Date(); typeof null; typeof window  
   "undefined" // typeof undefined; typeof 未定义变量
   "symbol"  // typeof Symbol();

2. 判断对象类型--instanceof

instanceof 的原理是检查右边构造函数的prototype属性是否在左边实例对象的原型链上。

instanceof(a, B) {// a代表实例对象;b代表构造函数
   a = a.__proto__;
   B = B.prototype;
   while(true) {
      if (a === null) {// 原型链顶层
          return false;
      }
      if(a === B) {
         return true;
      }
      a = a.__proto__;
   }
}

instanceof命令本质上调用的是构造函数上的静态方法[Symbol.hasInstance]。

⚠️:原生的构造函数该方法不能被覆写。

可以通过在自定义的构造函数上添加静态方法[Symbol.hasInstance]自定义实现instanceof 命令。  

 

class IsStr{
  static [Symbol.hasInstance](x) {
    return typeof x === 'string';
  }
}
console.log('' instanceof IsStr); //true

所以下面的实例如果 instanceof Object 全部为true

    ([2]) instanceof Array  -> true
    (new Date()) instanceof Date -> true
    (function(){}) instanceof Function  -> true
    ({}) instanceof Object  -> true

    null,undefined 使用该运算法的时候,返回值永远是 false

三 判断对象类型 constructor

   constructor属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。

    constructor属性是prototype对象上的属性,实例对象本身没有这个属性,调用的是原型对象上的constructor。

    因为js规定P.prototype.constructor === P

    (new Date()).constructor === Date  -> true
    ([2]).constructor === Array -> true
    (function(){}).constructor ===  Function  -> true
    ({}).constructor === Object  -> true

⚠️PS:instanceof 和 constructor 两者区别:

instanceof考虑的是原型链

function A(){};
function B(){};
A.prototype = new B(); // 构造函数A的原型是B的实例
var aobj = new A(); 
console.log(aobj.constructor === B) / //true
console.log(aobj.constructor === A)  //false
console.log(aobj instanceof A)          //true
console.log(aobj instanceof B)          //true 

类不通过prototype属性进行原型继承,es6的class中prototype是只读属性。

class A {}
Object.getOwnPropertyDescriptor(A, "prototype");
/*
      { 
          "value": constructor,
          "writable": false,
          "enumerable": false,
          "configurable": false 
      }
*/
      class A{};
      class B{};
      A.prototype = new B();
      var aobj = new A(); 
      console.log(aobj.constructor === B)  //false
      console.log(aobj.constructor === A)  //true
      console.log(aobj instanceof A)       //true
      console.log(aobj instanceof B)       //false 

四. 通用方法   

  缺点: 只能判断原生的数据类型,自定义的无法判断。

   Object.prototype.toString() 默认返回类型字符串。所有的值都继承该方法。

   但是数组、字符串、函数、Date 对象都又定义了属于自己的toString方法,覆盖了继承的Object.prototype的toString()方法。

   所以为了可以判断所有的类型,统一使用Object.prototype.toString.call(value),来判断数据类型。

   call方法是用于改变this的指向,value就是方法运行时的实例对象,如果value是原始值,会自动将其转为对应的包装对象。

  • 数值:返回[object Number]
  • 字符串:返回[object String]
  • 布尔值:返回[object Boolean]
  • undefined:返回[object Undefined]
  • null:返回[object Null]
  • 数组:返回[object Array]
  • arguments 对象:返回[object Arguments]
  • 函数:返回[object Function]
  • Error 对象:返回[object Error]
  • Date 对象:返回[object Date]
  • RegExp 对象:返回[object RegExp]
  • 其他对象:返回[object Object]。 

 *************判断一个变量是否是对象的方法*************

function isObject(value) {
  return   value === Object(value)
}
// 注意,原始类型的值通过Object()函数之后,会变成对应的包装对象;
// 对象(数组,对象,函数)等于本身

**************************************************** 

 

posted @ 2019-03-04 16:03  Lyra李  阅读(1551)  评论(0编辑  收藏  举报