javascript中判断数据类型

编写javascript代码的时候常常要判断变量,字面量的类型,可以用typeof,instanceof,Array.isArray(),等方法,究竟哪一种最方便,最实用,最省心呢?本问探讨这个问题。

1.1 语法

typeof返回一个字符串,表示未经计算的操作数的类型。

语法:typeof(operand) | typeof operand
参数:一个表示对象或原始值的表达式,其类型将被返回
描述:typeof可能返回的值如下:

类型 结果 Undefined “undefined” Null “object” Boolean “boolean” Number “number” Bigint “bigint” String “string” Symbol “symbol” 宿主对象(由JS环境提供) 取决于具体实现 Function对象 “function” 其他任何对象 “object”

从定义和描述上来看,这个语法可以判断出很多的数据类型,但是仔细观察,typeof null居然返回的是”object”,让人摸不着头脑,下面会具体介绍,先看看这个效果:

1.2 迷之null

javascript诞生以来,typeof null都是返回’object’的,这个是因为javascript中的值由两部分组成,一部分是表示 类型的标签,另一部分是表示 实际的值。对象类型的值类型标签是0,不巧的是null表示空指针,它的类型标签也被设计成0,于是就有这个typeof null === ‘object’这个’恶魔之子’。

曾经有ECMAScript提案让typeof null返回’null’,但是该提案被拒绝了。

1.3 使用new操作符

除Function之外所有构造函数的类型都是’object’,如下:

1.4 语法中的括号

typeof运算的优先级要高于”+”操作,但是低于圆括号

1.5 判断正则表达式的兼容性问题

1.6 错误

ECMAScript 2015之前,typeof总能保证对任何所给的操作数都返回一个字符串,即使是没有声明,没有赋值的标示符,typeof也能返回undefined,也就是说使用typeof永远不会报错。

但是ES6中加入了块级作用域以及let,const命令之后,在变量声明之前使用由let,const声明的变量都会抛出一个ReferenceError错误,块级作用域变量在块的头部到声明变量之间是”暂时性死区”,在这期间访问变量会抛出错误。如下:

1.7 例外

当前所有浏览器都暴露一个类型为undefined的非标准宿主对象document.all。typeof document.all === ‘undefined’。景观规范允许为非标准的外来对象自定义类型标签,单要求这些类型标签与已有的不同,document.all的类型标签为undefined的例子在web领域被归类为对原ECMA javascript标准的”故意侵犯”,可能就是浏览器的恶作剧。

总结:typeof返回变量或者值的类型标签,虽然对大部分类型都能返回正确结果,但是对null,构造函数实例,正则表达式这三种不太理想。

2.1 语法

instanceof运算符用于检测实例对象(参数)的原型链上是否出现构造函数的prototype。

语法:object instanceof constructor
参数:object 某个实例对象
constructor 某个构造函数
描述:instanceof运算符用来检测constructor.property是否存在于参数object的原型链上。

需要注意的是,如果表达式obj instanceof Foo返回true,则并不意味着该表达式会永远返回true,应为Foo.prototype属性的值可能被修改,修改之后的值可能不在obj的原型链上,这时表达式的值就是false了。另外一种情况,改变obj的原型链的情况,虽然在当前ES规范中,只能读取对象的原型而不能修改它,但是借助非标准的__proto__伪属性,是可以修改的,比如执行obj.proto = {}后,obj instanceof Foo就返回false了。此外ES6中Object.setPrototypeOf(),Reflect.setPrototypeOf()都可以修改对象的原型。

instanceof和多全局对象(多个iframe或多个window之间的交互)

浏览器中,javascript脚本可能需要在多个窗口之间交互。多个窗口意味着多个全局环境,不同全局环境拥有不同的全局对象,从而拥有不同的内置构造函数。这可能会引发一些问题。例如表达式[] instanceof window.frames[0].Array会返回false,因为Array.prototype !== window.frames[0].Array.prototype。

起初,这样可能没有意义,但是当在脚本中处理多个frame或多个window以及通过函数将对象从一个窗口传递到另一个窗口时,这就是一个非常有意义的话题。实际上,可以通过Array.isArray(myObj)或者Object.prototype.toString.call(myObj) = “[object Array]”来安全的检测传过来的对象是否是一个数组。

2.2 示例

String对象和Date对象都属于Object类型(它们都由Object派生出来)。

但是,使用对象文字符号创建的对象在这里是一个例外,虽然原型未定义,但是instanceof of Object返回true。

注意:instanceof运算符的左边必须是一个对象,像”string” instanceof String,true instanceof Boolean这样的字面量都会返回false。

下面代码创建了一个类型Car,以及该类型的对象实例mycar,instanceof运算符表明了这个myca对象既属于Car类型,又属于Object类型。

不是…的实例

要检测对象不是某个构造函数的实例时,可以使用!运算符,例如if(!(mycar instanceof Car))

instanceof虽然能够判断出对象的类型,但是必须要求这个参数是一个对象,简单类型的变量,字面量就不行了,很显然,这在实际编码中也是不够实用。

总结:obj instanceof constructor虽然能判断出对象的原型链上是否有构造函数的原型,但是只能判断出对象类型变量,字面量是判断不出的。

3.1. 语法

toString()方法返回一个表示该对象的字符串。

语法:obj.toString()
返回值:一个表示该对象的字符串
描述:每个对象都有一个toString()方法,该对象被表示为一个文本字符串时,或一个对象以预期的字符串方式引用时自动调用。默认情况下,toString()方法被每个Object对象继承,如果此方法在自定义对象中未被覆盖,toString()返回”[object type]”,其中type是对象的类型,看下面代码:

注意:如ECMAScript 5和随后的Errata中所定义,从javascript1.8.5开始,toString()调用null返回[object, Null],undefined返回[object Undefined]

3.2. 示例

覆盖默认的toString()方法

可以自定义一个方法,来覆盖默认的toString()方法,该toString()方法不能传入参数,并且必须返回一个字符串,自定义的toString()方法可以是任何我们需要的值,但如果带有相关的信息,将变得非常有用。

下面代码中定义Dog对象类型,并在构造函数原型上覆盖toString()方法,返回一个有实际意义的字符串,描述当前dog的姓名,颜色,性别,饲养员等信息。

目前来看toString()方法能够基本满足javascript数据类型的检测需求,可以通过toString()来检测每个对象的类型。为了每个对象都能通过Object.prototype.toString()来检测,需要以Function.prototype.call()或者Function.prototype.apply()的形式来检测,传入要检测的对象或变量作为第一个参数,返回一个字符串”[object type]”。

上面的结果,除了NaN返回Number稍微有点差池之外其他的都返回了意料之中的结果,都能满足实际开发的需求,于是我们可以写一个通用的函数来检测变量,字面量的类型。如下:

除了能检测ECMAScript规定的八种数据类型(七种原始类型, BooleanNullUndefinedNumberBigIntStringSymbol,一种复合类型 Object)之外,还能检测出正则表达式 RegExpFunction这两种类型,基本上能满足开发中的判断数据类型需求。

既然说道这里,不妨说一说另一个开发中常见的问题,判断一个变量是否等于一个值。ES5中比较两个值是否相等,可以使用相等运算符(==),严格相等运算符(===),但它们都有缺点,== 会将’4’转换成4,后者NaN不等于自身,以及+0 !=== -0。ES6中提出”Same-value equality”(同值相等)算法,用来解决这个问题。Object.is就是部署这个算法的新方法,它用来比较两个值是否严格相等,与严格比较运算(===)行为基本一致。

Object.js()不同之处有两处,一是+0不等于-0,而是NaN等于自身,如下:

注意两个空对象不能判断相等,除非是将一个对象赋值给另外一个变量,对象类型的变量是一个指针,比较的也是这个指针,而不是对象内部属性,对象原型等。

Original: https://www.cnblogs.com/tylerdonet/p/11852391.html
Author: nd
Title: javascript中判断数据类型

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/536123/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • JavaScript 图片滑动切换效果

    序一(08/07/06) 看到alibaba的一个图片切换效果,感觉不错,想拿来用用。但代码一大堆的,看着昏,还是自己来吧。由于有了做图片滑动展示效果的经验,做这个就容易得多了。 …

    JavaScript 2023年5月29日
    070
  • Javascript 严格模式

    严格模式是一种将更好的错误检查引入代码中的方法。 在使用严格模式时,你无法使用隐式声明的变量、将值赋给只读属性或将属性添加到不可扩展的对象等。 声明严格模式 可以通过在文件、程序或…

    JavaScript 2023年5月29日
    053
  • javascript中的call()和apply()方法的使用

    1、方法定义 call方法:语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])定义:调用一个对象的一个方法,以另一个对象替换当前对象。说明:…

    JavaScript 2023年5月29日
    052
  • 【前端安全】JavaScript防XSS攻击

    什么是XSS XSS(Cross Site Scripting),跨站脚本攻击,是一种允许攻击者在另外一个用户的浏览器中执行恶意代码脚本的脚本注入式攻击。本来缩小应该是CSS,但为…

    JavaScript 2023年5月29日
    0110
  • javascript 闭包最简单理解

    首先说3点与闭包有关系的东西。 一、变量的作用域 变量的作用域不难理解。 1.函数内部可以访问函数外部的变量,而函数外部不能访问函数内部的变量。 2.如果在函数内定义变量的时候,不…

    JavaScript 2023年5月29日
    072
  • 如何编写 Cloud9 JavaScript IDE 的功能扩展

    require.def第一个参数标识扩展的名字,第二参数中 ide,ext ,util和 editors 代表传入该扩展依赖的对象引用,formatjson扩展的第五个依赖是加载为…

    JavaScript 2023年5月29日
    059
  • 关于javascript 正则中连续执行返回null的问题

    最近在使用javascript 判断是否是手机浏览器中遇到一个问题 发现先使用test判断是否匹配,再使用exec获取id时,尽然返回为null。如果再前面执行一次exec,再执行…

    JavaScript 2023年5月29日
    094
  • JavaScript 拖放效果

    拖放效果,也叫拖拽、拖动,学名Drag-and-drop ,是最常见的js特效之一。如果忽略很多细节,实现起来很简单,但往往细节才是难点所在。这个程序的原型是在做图片切割效果的时候…

    JavaScript 2023年5月29日
    067
  • javascript: TimelineJS3 Examples

    demo Timeline examples: Autoloading Timeline Slideshow (dusystem.com) Unicode 15.0 2022 ht…

    JavaScript 2023年5月29日
    080
  • “5W1H”带你来学习JavaScript

    上次的设计模式讲课,从中学习到了非常多。不仅是技术上,更重要的是怎样来学习。我们学习的技术。科技的更新速度超过我们的想象,对于我们这个有生命年限的个体,怎样可以在有生之年可以让自己…

    JavaScript 2023年5月29日
    080
  • 桶排序JavaScript

    // 桶排序 // 公式 // 桶的数量 = ((最大值 – 最小值)/ 数组长度) + 1 // 元素所属桶的位置 =( 元素大小 – 最小值)/ 数组长度 function b…

    JavaScript 2023年5月29日
    059
  • JavaScript的OOP编程2

    我做了一个observer的设计模式实现 version1 // ————————————————– functi…

    JavaScript 2023年5月29日
    075
  • javascript 中==和===的区别

    对于JavaScript中比较运算符,可能大家用的比较多的是”==”、对于”===”很多人可能很陌生。=== 表示恒等,首先比较两边…

    JavaScript 2023年5月29日
    070
  • JavaScript 图片切割效果

    序一(08/07/21) 很久之前就在一个网站的截取相片的功能中看到这个效果,也叫图片裁剪、图片剪切(设置一下也可以做出放大镜等类似的效果)。当时觉得很神奇,碍于水平有限,没做出来…

    JavaScript 2023年5月29日
    067
  • 12个实用的 JavaScript 框架分享给前端开发者

    JavaScript库是预先编写的 JavaScript 工具代码,让开发者可以更容易开发 JavaScript 应用。这个列表我们列出了2017年1月份功能丰富的 JavaScr…

    JavaScript 2023年5月29日
    052
  • 把C编译成javascript的方法

    把C编译成javascript的方法 把C编译成javascript的方法,便于嵌入到HTML5中 https://github.com/kripken/emscripten Or…

    JavaScript 2023年5月29日
    060
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球