js判断数据类型的方法

typeof

返回的结果用该类型的字符串(全小写字母)形式表示,包括以下 7 种:string、number、boolean、symbol、undefined、object、function 等。

  <script>
    var a = "iamstring.";
    var b = 222;
    var c= [1,2,3];
    var d = new Date();
    var e = function(){};
    var f = null
    var g
    var h = true

    console.log(typeof a);  // string
    console.log(typeof b);  // number
    console.log(typeof c);  // object
    console.log(typeof d);  // object
    console.log(typeof e);  // function
    console.log(typeof f);  // object
    console.log(typeof g);  // undefined
    console.log(typeof h);  // boolean
    console.log(typeof i);  // symbol
  </script>

其中typeof返回的类型都是字符串形式,需注意,例如:

    console.log(typeof a =="string"); // true
    console.log(typeof a == String); // false

对于基本类型,除 null 以外,均可以返回正确的结果。
对于引用类型,除 function 以外,一律返回 object 类型。
对于 null ,返回 object 类型。
对于 function 返回 function 类型。

typeof 在判断 null、array、object以及函数实例(new + 函数)时,得到的都是 object。使得在判断这些数据类型的时候,得不到真实的数据类型。

null 有属于自己的数据类型 Null ,引用类型中的数组、日期、正则 也都有属于自己的具体类型,而 typeof 对于这些类型的处理,只返回了处于其原型链最顶端的 Object 类型。

instanceof

instanceof 检测的是原型,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。它不能用来检测基本数据类型。B 的值如果是 Null 或者是 Undefined 会直接报错。

instanceof 后面一定要是对象类型,并且大小写不能错。

    console.log(a instanceof String); // falese
    console.log(b instanceof Number); // false
    console.log(c instanceof Array); // true
    
    console.log(c instanceof Object); // true
    
    console.log(d instanceof Date); // true
    console.log(e instanceof Function); // true
    
    console.log(e instanceof Object); // true
    
    console.log(h instanceof Boolean); // false
    console.log(i instanceof Symbol); // false

虽然 instanceof 能够判断出 c 是Array的实例,但它认为 c 也是Object的实例

从 instanceof 能够判断出 c.__ proto__ 指向 Array.prototype,而 Array.prototype.__ proto__ 又指向了Object.prototype,最终 Object.prototype.__ proto__ 指向了null,标志着原型链的结束。因此,c、Array、Object 就在内部形成了一条原型链。

从原型链可以看出,c 的 __ proto__ 直接指向Array.prototype,间接指向 Object.prototype,所以按照 instanceof 的判断规则,c 就是Object的实例。依次类推,类似的 new Date()、new Person() 也会形成一条对应的原型链 。

因此,instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。

针对数组的这个问题,ES5 提供了 Array.isArray() 方法 。该方法用以确认某个对象本身是否为 Array 类型,而不区分该对象在哪个环境中创建。

console.log(Array.isArray(c)); // true

Array.isArray() 本质上检测的是对象的 [[Class]] 值。
[[Class]] 是对象的一个内部属性,里面包含了对象的类型信息,其格式为 [object Xxx]Xxx 就是对应的具体类型 。对于数组而言,[[Class]] 的值就是 [object Array] 。

constructor

constructor 判断方法跟 instanceof 相似,但是 constructor 检测 Object 与 instanceof 不一样。constructor 还可以处理基本数据类型的检测

null 和 undefined 没有 constructor
判断数字时使用(),比如 (123).constructor ,如果写成 123.constructor 会报错

    console.log(a.constructor === String); // true
    console.log(b.constructor === Number); // true
    console.log(c.constructor === Array); // true
    console.log(c.constructor === Object); // false
    console.log(d.constructor === Date); // true
    console.log(e.constructor === Function); // true
    console.log(h.constructor === Boolean); // true
    console.log(i.constructor === Symbol); // true
    console.log({}.constructor === Object); //true

当一个函数 Fun 被定义时,JS引擎会为 Fun 添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 Fun 的引用。

Fun.prototype.constructor == Fun    // true

当执行 var fun = new Fun() 时,Fun 被当成了构造函数,fun 是 Fun 的实例对象,此时 Fun 原型上的 constructor 传递到了 fun 上,因此 fun.constructor == Fun

Fun 利用原型对象上的 constructor 引用了自身,当 Fun 作为构造函数来创建对象时,原型上的 constructor 就被遗传到了新创建的对象上, 从原型链角度讲,构造函数 Fun 就是新对象的类型。这样做的意义是,让新对象在诞生以后,就具有可追溯的数据类型。

constructor 在类继承时会出错,因为Object被覆盖掉了,检测结果就不对了
A.prototype.__ proto__ 本来应该等于 Object.prototype 但现在等于 B.prototype

    function A(){}
    console.log(A.prototype.__proto__ === Object.prototype); // true
    
    function B(){}
    A.prototype = new B() // A 继承自 B
    var C = new A()
    console.log(A.prototype.constructor === B); // true   A的实例继承的 constructor 就是 B
    
    console.log(A.prototype.__proto__ === B.prototype); // true
    
    console.log(C.constructor === A); // false
    console.log(C.constructor === B); // true
    
    // 而instanceof方法不会出现该问题,对象直接继承和间接继承的都会报true
    console.log(C instanceof A); // true
    console.log(C instanceof B); // true
    
    // 解决这种问题,通常是手动调整 constructor的指向
    console.log(C.constructor === A); // true
    console.log(C.constructor === B); // false

Object.prototype.toString.call() 非常通用!!

toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。

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

Object对象本身就有一个toString()方法,返回的是当前对象的字符串形式,原型上的toString()返回的才是我们真正需要的包含对象数据类型的字符串。

由于Object.prototype.toString()本身允许被修改,像Array、Boolean、Number的toString就被重写过,所以需要调用Object.prototype.toString.call(arg)来判断arg的类型,call将arg的上下文指向Object,所以arg执行了Object的toString方法。

var a = "iamstring.";
    var b = 222;
    var c= [1,2,3];
    var d = new Date();
    var e = function(){};
    var f = null
    var g
    var h = true
    var i = Symbol()
    var j = {}

    console.log(Object.prototype.toString.call(a)); // [object String]
    console.log(Object.prototype.toString.call(b)); // [object Number]
    console.log(Object.prototype.toString.call(c)); // [object Array]
    console.log(Object.prototype.toString.call(d)); // [object Date]
    console.log(Object.prototype.toString.call(e)); // [object Function]
    console.log(Object.prototype.toString.call(f)); // [object Null]
    console.log(Object.prototype.toString.call(g)); // [object Undefined]
    console.log(Object.prototype.toString.call(h)); // [object Boolean]
    console.log(Object.prototype.toString.call(i)); // [object Symbol]
    console.log(Object.prototype.toString.call(j)); // [object Object]

在这里插入图片描述
不同的数据类型都有其自身toString()方法。在JavaScript中,所有类都继承于Object,因此toString()方法应该也被继承了,但由上述可见事实并不像我们想的那样,其实各数据类型使用toString()后的结果表现不一的原因在于:所有类在继承Object的时候,改写了toString()方法Object原型上的方法是可以输出数据类型的。因此我们想判断数据类型时,也只能使用原始方法。 继而有了此方法:Object.prototype.toString.call(obj)

可以把Array自身的toString()方法删除,再次使用它时,由原型链它会向上查找这个方法,即Object的toString(),也便将Object上的toString()方法作用在数组上,得出其数据类型[object Array]

// 定义一个数组
var arr = [1, 2, 3]

// 数组原型上是否具有 toString() 方法
console.log(Array.prototype.hasOwnProperty('toString')) //true

// 数组直接使用自身的 toString() 方法
console.log(arr.toString()) // '1,2,3'

// delete操作符删除数组原型上的 toString()
delete Array.prototype.toString

// 删除后,数组原型上是否还具有 toString() 方法
console.log(Array.prototype.hasOwnProperty('toString')) //false

// 删除后的数组再次使用 toString() 时,会向上层访问这个方法,即 Object 的 toString()
console.log(arr.toString()) // '[object Array]'

代码、理论知识及图片绝大多数来自看过的博客&视频
俺只是加以整合并写了部分注释便于自己理解

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值