资讯专栏INFORMATION COLUMN

js数据类型及类型检测

Kyxy / 594人阅读

摘要:使用的构造函数是,它只为新对象定义了默认的属性和方法。如果网页中包含多个框架,那实际上就存在多个不同的全局执行环境,从而存在多个不同版本的构造函数。每个类在内部都有一个属性,这个属性中就指定了上述字符串中的构造函数。

js中常见的用于类型判断的操作符或属性有:typeof、instanceof、prototype。下面我们就来看看他们是如何判断数据类型的。

一.js数据类型

ECMAscript中有5种简单数据类型(基本数据类型):UndefinedNullBooleanNumberString。除了这五种基本数据类型之外,还有一种复杂类型值(引用类型)。引用类型又分为:原生引用类型和自定义引用类型。在ECMAscript中,引用类型是一种数据结构,用于将数据和功能无序地组织在一起,以key/value的形式在对象中存放。ECMAscript不支持任何创建自定义类型的机制,而所有值最终都将是上述6种数据类型之一。另外,对象是某个特定引用类型的实例,例如:

var person = new Object()

这行代码创建了Object引用类型的一个新实例,然后把该实例保存在了person中。使用的构造函数是Object,它只为新对象定义了默认的属性和方法。Object只是ECMAscript提供的原生引用类型的一种。诸如Array、Date、RegExp、Function、Boolean、Number、String也都是内置的原生引用类型。

二.typeof

基本类型的检验,经常使用typeof操作符。对一个值使用typeof操作符可能返回下列某个字符串:

"undefined"———如果这个值未定义
"boolean"———如果这个值是布尔值
"string"———如果这个值是字符串
"number"———如果这个值是数值
"object"———如果这个值是对象或null
"function"———如果这个值是函数

调用typeof null会返回"object",因为特殊值null被认为是一个空的对象的引用。

Safari及之前版本、Chrome7及之前版本在对正则表达式调用typeof操作符时会返回"function",而其它浏览器在这种情况下会返回"object"。

从技术角度讲,函数在ECMAscript中是对象,不是一种数据类型。然而,函数也确实有一些特殊的属性,因此通过typeof操作符来区分函数和其它对象是有必要的。

三.instanceof

在 JavaScript 中,判断一个变量的类型尝尝会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 "object"。ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。通常来讲,使用 instanceof 就是判断一个实例是否属于某种类型。例如:

// 判断 boy是否是 People类的实例
function People(){} 
var boy= new People(); 
console.log(boy instanceof People)//true

与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。例如:

var arr = [1,2,3]
if(arr instanceof Array){
    console.log(“arr是一个数组”)
}
//输出:arr是一个数组

这段代码问的是“变量 arr是否为 Array对象的实例?”arr的确是 Array对象的实例,因此结果是"true"。尽管不像 typeof 方法那样灵活,但是在 typeof 方法返回 "object" 的情况下,instanceof 方法还是很有用的。
但是,instanceof操作符并不是安全的检测方式。instanceof操作符的问题在于,它假定只有一个全局执行环境。如果网页中包含多个框架frame,那实际上就存在多个不同的全局执行环境,从而存在多个不同版本的Array构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。为了解决这个问题,ES5中新增了Array.isArray()方法。这个方法的目的是最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的。这个方法是用如下:

if(Array.isArray(arr)){
    //do sometion
}

目前,支持Array.isArray()方法的浏览器有IE9+、Firefox 4+、Safari 5+、Opera 10.5+、Chrome。要在尚未实现这个方法的浏览器中准确检测数组,请参考“四.安全的类型检测”。

instanceof究竟是运算什么的?

我曾经简单理解instanceof只是检测一个对象是否是另个对象new出来的实例(例如var a = new Object(),a instanceof Object返回true),但实际instanceof的运算规则上比这个更复杂。

//假设instanceof运算符左边是L,右边是R
L instanceof R 
//instanceof运算时,通过判断L的原型链上是否存在R.prototype
L.__proto__.__proto__ ..... === R.prototype ?
//如果存在返回true 否则返回false

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

所以一句话理解instanceof的运算规则为:

instanceof检测左侧的__proto__原型链上,是否存在右侧的prototype原型。

知道了这个也就知道为什么以下这些奇怪的表达式为什么会得到相应的值了

 Function instanceof Object // true 
 Object instanceof Function // true 
 Function instanceof Function //true
 Object instanceof Object // true
 Number instanceof Number //false
 

那么知道了原理之后,如何自己手写一个instanceof,如下所示:

function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
 var O = R.prototype;// 取 R 的显示原型
 L = L.__proto__;// 取 L 的隐式原型
 while (true) { 
   if (L === null) {
     return false; 
   }
   if (O === L) {// 这里重点:当 O 严格等于 L 时,返回 true 
     return true;
   } 
   L = L.__proto__; 
 } 
}
instance_of(Function,Function)//true
instance_of(String,String)//true

JavaScript instanceof 运算符深入剖析https://www.ibm.com/developer...

四.安全的类型检测

在检测某个对象到底是原生对象还是开发人员自定义的对象的时候,也会有问题。出现这个问题的原因是浏览器开始原生支持JSON对象了。因为很多人一直在使用Douglas的JSON库,而该库定义了一个全局的JSON对象。于是开发人员很难确定页面中的JSON对象到底是不是原生的。
解决typeof、instanceof和判断是否是原生JSON对象的方法都一样。大家都知道,在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串。每个类在内部都有一个[[Class]]属性,这个属性中就指定了上述字符串中的构造函数。举个栗子:

var o = [];
alert(Object.prototype.toString.call(o));//"[object Array]"

由于原生数组的构造函数名与全局作用域无关,因此使用toString()就能保证返回一致的值。利用这一点,可以创建如下函数:

function isArray(value){
    return Object.prototype.toString.call(value) == "[object Array]"
}

同样,也可以基于这一思路来测试某个值是不是原生函数或正则表达式:

function isFunction(value){
    return Object.prototype.toString.call(value) == "[object Function]"
}

function isRegExp(value){
    return Object.prototype.toString.call(value) == "[object RegExp]"
}

Object的toString()方法不能检测非原生构造函数的构造函数名,因此,开发人员定义的任何构造函数都将返回"[object Object]"。这也就是为什么在上图中的序号③处调用test(p)会返回"[object Object]"的原因了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94213.html

相关文章

  • 重学JS: 数据类型类型检测

    摘要:数据类型七种内置类型空值未定义布尔值数字字符串对象符号除对象之外,其他统称为基本类型类型检测运算符后面跟操作数,或者,返回一个类型的字符串值。运算符用于测试构造函数的属性是否出现在对象的原型链中的任何位置。 数据类型 JavaScript七种内置类型: 空值(null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符串(string) 对象(obj...

    why_rookie 评论0 收藏0
  • 《javascript高级程序设计》笔记:变量变量检测

    摘要:变量的特点变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。 变量的特点 js变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。换句话说, 每个变量仅仅是一个用于保存值的占位符而已 js变量可以用来保存任何值,未经过初始化的变量,会保存一个特殊的值—undefined,如:var msg; js变量的初始化并不会为它标记类型;初始化的过程就是给变量赋一个值那...

    XiNGRZ 评论0 收藏0
  • JavaScript红宝书笔记(一)---JS概述、变量基本数据类型

    摘要:是一个数值可以被转换成数值不能转换成数值可以被转换成数值十六进制数八进制数十进制数十六进制数可以避免,无法使用方法转换成字符串的情况 1.JavaScript由三个部分组成:ECMAScript(提供核心语言功能)、DOM(文档对象模型,提供访问和操作网页内容的方法和接口)、BOM(浏览器对象模型,提供与浏览器交互的方法和接口) 2.JavaScript概念:是一种专为与网页交互而设计...

    sevi_stuo 评论0 收藏0
  • XSS分析预防

    摘要:分析及预防,又称跨站脚本,的重点不在于跨站点,而是在于脚本的执行。在这里需要强调一点的是,默认会禁止代码块的执行禁止内联事件处理函数禁止内联样式禁止和。 XSS分析及预防 XSS(Cross Site Scripting),又称跨站脚本,XSS的重点不在于跨站点,而是在于脚本的执行。在WEB前端应用日益发展的今天,XSS漏洞尤其容易被开发人员忽视,最终可能造成对个人信息的泄漏。如今,...

    smartlion 评论0 收藏0
  • 33 个 js 核心概念(二):数据类型

    摘要:举个例子在上面的例子可以看到,我们声明是一个数字,但是我们在之后将的值又改成了字符串和布尔值后面会讲这些类型。基本类型字符串表示一个字符串,如。因此,我们可以写一个函数,用来精确检测类型。 showImg(https://segmentfault.com/img/remote/1460000017309509?w=850&h=572); 定义 1. 什么是数据类型? 数据类型,就是将...

    QiShare 评论0 收藏0

发表评论

0条评论

Kyxy

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<