JavaScript类型判断

简介: JavaScript类型判断

1.typeof



var a;
console.log("1:" + typeof a);
var b = null;
console.log("2:" + typeof b);
var c = undefined;
console.log("3:" + typeof c);
var d = new Object;
console.log("4:" + typeof d);
var e = function() {};
console.log("5:" + typeof e);
var f = {};
console.log("6:" + typeof f);
var g = '';
console.log("7:" + typeof g);
var h = [];
console.log("8:" + typeof h);
var i = true;
console.log("9:" + typeof i);
var j = 123;
console.log("10:" + typeof j);
var k = NaN;
console.log("11:" + typeof k);
var l = /^[-+]?\d+$/;
console.log("12:" + typeof l);


打印结果如下


image.png


总结:typeof对null、undefined、NaN、数组、正则、Object的类型都为object


2.constructor


constructor 用于判断一个变量的原型,constructor 属性返回对创建此对象的数组函数的引用.当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用,当执行 var f = new F() 时,F 被当成了构造函数,f 是F的实例对象,此时 F 原型上的 constructor 传递到了 f 上,因此 f.constructor === F

var F = function(){}
console.log(F.prototype);
var f = new F();
console.log(f.constructor===F) //true


不难看出,F 利用原型对象上的 constructor 引用了自身,当 F 作为构造函数来创建对象时,原型上的 constructor 就被遗传到了新创建的对象上, 从原型链角度讲,构造函数 F 就是新对象的类型。这样做的意义是,让新对象在诞生以后,就具有可追溯的数据类型,也就是说对象的constructor属性指向他的构造函数所以内置对象在内部构建时阔以这样做出判断


image.png



  • null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断
  • constructor属性并非一定指向构造函数,他也是可以修改、变更的(当把F.prototype = {}改写后,会默认把constructor覆盖掉)


instanceof


instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性

及的构造函数有这些基础类型:StringNumberBoolean、Undefined、Null、Symbol(ES6引入了一种新的原始数据类型Symbol,表示独一无二的值);


复杂类型:ArrayObject


其他类型:FunctionRegExpDate


var obj = newObject()


obj instanceofObject// true


注意左侧必须是对象(object),如果不是,直接返回false,列如:


var num = 1
num instanceof Number // false
num = new Number(1)
num instanceof Number // true


可以看出都是num,而且都是1,只是因为第一个不是对象,是基本类型,所以直接返回false,而第二个是封装成对象,所以true。


这里要严格注意这个问题,有些说法是检测目标的__proto__与构造函数的prototype相同即返回true,这是不严谨的,检测的一定要是对象才行,如:


基础类型


var num = 1
num.__proto__ === Number.prototype // true
num instanceof Number // false
num = new Number(1)
num.__proto__ === Number.prototype // true
num instanceof Number // true
num.__proto__ === (new Number(1)).__proto__ // true


上面例子可以看出,1与new Number(1)几乎是一样的,只是区别在于是否封装成对象,所以instanceof的结果是不同的,string、boolean等,这些基础类型一样的。


new String(1) // String {"1"}
String(1) // "1"


new String(1)与String(1)是不同的,new是封装成对象,而没有new的只是基础类型转换,还是基础类型


其他基础类型一样的。


复杂类型,比如数组与对象,甚至函数等,与基础类型不同。


复杂类型


var arr = []
arr instanceof Array // true
arr instanceof Object // true
Array.isArray(arr) // true


复杂类型从字面量是直接生成构造函数的,所以不会像基本类型一样两种情况。


但是上面那个问题,当然,基础类型也会有这个问题,就是与Object对比。没办法,Object在原型链的上层,所以都会返回true,如下:


(new Number(1)) instanceof Object // true


由于从下往上,比如你判断是Number,那就没必要判断是不是Object了,因为已经是Number了……


其他类型


var reg = new RegExp(//)
reg instanceof RegExp // true
reg instanceof Object // true
var date = new Date()
date instanceof Date // true
date instanceof Object // true
除了Function,都一样,具体Function如下:
function A() {}
var a = new A()
a instanceof Function // false
a instanceof Object // true
A instanceof Function // true


这里要注意,function A() {}相当于var A; A = function() {},然后分析:


  1. a是new出来,所以是经过构造,因此已经是对象,不再是函数,所以false
  2. a是经过构造的对象,返回ture没问题
  3. A是个函数,这没什么问题


{}.toString.call(obj)


用法如下


console.log({}.toString.call(1));
console.log({}.toString.call("11"));
console.log({}.toString.call(/123/));
console.log({}.toString.call({}));
console.log({}.toString.call(function() {}));
console.log({}.toString.call([]));
console.log({}.toString.call(true));
console.log({}.toString.call(new Date()));
console.log({}.toString.call(new Error()));
console.log({}.toString.call(null));
console.log({}.toString.call(undefined));
console.log(String(null));
console.log(String(undefined));


返回如下


image.png


注意:必须通过 call 或 apply 来调用,而不能直接调用 toString , 从原型链的角度讲,所有对象的原型链最终都指向了 Object, 按照JS变量查找规则,其他对象应该也可以直接访问到 Object 的 toString方法,而事实上,大部分的对象都实现了自身的 toString 方法,这样就可能会导致 Object 的 toString 被终止查找,因此要用 call/apply 来强制调用Object 的 toString 方法


jQuery中的方法$.type(),就是用到了toString


type: function( obj ) {
    if ( obj == null ) {
        return obj + "";
    }
    // Support: Android<4.0, iOS<6 (functionish RegExp)
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ toString.call(obj) ] || "object" :
        typeof obj;
},


分析源代码:


typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call(obj) ]


通过判断传入类型,如果是object或者function类型就直接返回class2type 中键值是对的结果,如果不是,那么一定就是基本类型, 通过 typeof 就可以


class2type[ toString.call(obj) ] || "object"


这是为了防止一些未知情况的,如果未取到,就返回object,保证了程序可用性

相关文章
|
3月前
|
JavaScript 前端开发 开发者
如何在 JavaScript 中处理不同类型的错误?
【10月更文挑战第29天】通过对不同类型错误的准确识别和恰当处理,可以提高JavaScript程序的可靠性和稳定性,减少错误对程序运行的影响。
|
4月前
|
JavaScript 前端开发 安全
深入理解TypeScript:增强JavaScript的类型安全性
【10月更文挑战第8天】深入理解TypeScript:增强JavaScript的类型安全性
80 0
|
6月前
|
前端开发 JavaScript 搜索推荐
Next.js 适合什么类型的项目开发?
【8月更文挑战第4天】Next.js 适合什么类型的项目开发?
298 3
|
3月前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
60 2
|
3月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
71 4
|
3月前
|
JavaScript 前端开发 Java
除了 JavaScript,还有哪些编程语言支持 Set 类型
【10月更文挑战第30天】这些编程语言中的 `Set` 类型虽然在语法和具体实现细节上有所不同,但都提供了类似的集合操作功能,方便开发者在不同的编程场景中处理集合相关的数据和逻辑。
|
3月前
|
存储 JavaScript 前端开发
js的基础类型和引用类型
【10月更文挑战第29天】理解 JavaScript 中的基础类型和引用类型的区别对于正确地编写代码和理解程序的行为非常重要。在实际开发中,需要根据具体的需求合理地选择和使用不同的数据类型,以避免出现一些意想不到的错误和问题。同时,在处理引用类型数据时,要特别注意对象的引用关系,避免因共享引用而导致的数据不一致等问题。
|
8月前
|
JavaScript 前端开发
JavaScript中的布尔类型与数字类型详解
JavaScript中的布尔类型与数字类型详解
|
4月前
|
JavaScript 前端开发
JavaScript返回判断类型有哪些?
JavaScript返回判断类型有哪些?
43 0
|
6月前
|
缓存 JavaScript 前端开发

热门文章

最新文章