JS专题之数据类型和类型检测
栏目: JavaScript · 发布时间: 5年前
内容简介:ECMAScript 的数据类型分为简单数据类型(也被称为基本数据类型,原始数据类型):在 ES6 中新增一个简单数据类型 Symbol,所以简单数据类型总共有 6 个,还有复杂数据类型(也叫作引用数据类型):Object。所有 js 中所有的值最终都将是以上 7 种数据类型之一。
ECMAScript 的数据类型分为简单数据类型(也被称为基本数据类型,原始数据类型):
- Undefined
- Null
- String
- Number
- Boolean
在 ES6 中新增一个简单数据类型 Symbol,所以简单数据类型总共有 6 个,还有复杂数据类型(也叫作引用数据类型):Object。
所有 js 中所有的值最终都将是以上 7 种数据类型之一。
基本数据类型
基本数据类型是保存在 栈
的数据结构中的,是按值访问的,基本数据类型的值不会变 (值本身无法被改变) 数据之间进行的是它们 值
的比较。
看代码:
var a,b; a = "jay_chou"; b = a; console.log(a); // jay_chou console.log(b); // jay_chou a = "coldplay"; // 改变 a 的值,并不影响 b 的值 console.log(a); // coldplay console.log(b); // jay_chou 复制代码
引用数据类型
除了基本的数据类型外,剩下的就是引用类型,统称为 Object 类型, 细分的话,有 Object 类型,Array 类型,Date 类型, Regexp 类型,function, Math 类型;
引用数据类型的特点:
- 引用数据类型的值保存的是对象在内存中的地址
- 引用数据类型的值是可变的
- 引用数据类型的比较是引用的比较
- 另外:js 不能直接操作对象的内存空间 比方:
var a = { name: "jay_chou" } var b = a; var c = { name: "jay_chou" } a === b; // true a === c; // false 复制代码
一、为什么要进行类型检测?
JavaScript 是动态语言,动态语言和静态语言的区别在于:类型是在编译时检查(静态)还是在运行时检查(动态)。
基于动态类型的特点,如果不注意进行类型检测,JS 很容易在运行代码发生才发现报错。
举个列子:
函数在定义时,参数可以是任何类型,但是函数在实际运行的时候,传入的实参可能是其他同事函数的返回值,也可能是后台的返回值,假如不符合代码逻辑里要求的数据类型,那么就会报错导致 bug 影响程序运行。
因此,我们不光要做类型检测,也应该给自己的函数注释好参数类型和返回值类型,还要和后端定义好接口数据类型格式。
当比较的两个值的类型不同的时候 ==
运算符会进行类型转换,但是当两个值的类型相同的时候,即使是 ==
也相当于是 ===
; ===
在比较两个值的时候,还会比较值的数据类型。
二、typeof 方式
typeof 的返回值总是字符串,字符串的可能值有:
- undefined
- boolean
- number
- string
- symbol
- object
- function
typeof 其实是一元操作符,和 + - * /
一样,不是一个函数,进行比较的时候,typeof 后面可以跟 ()
, 也可以不跟。
undefined:
typeof undefined; // undefined
很多库因为考虑到 undefined 可能会被意外重写,用 void 0
来判断是否是 undefined。
var isUndefined = function (obj) { return obj === void 0; } 复制代码
MDN 上对 void 词条的说明是:
The void operator evaluates the given expression and then returns undefined.
意思是说 void 运算符能对给定的表达式进行求值,然后返回 undefined。也就是说,void 后面你随便跟上一个表达式,返回的都是 undefined,都能完美代替 undefined。
string, number, boolean, symbol, function, object :
typeof "abc"; // string
typeof 123; // number
typeof NaN; // number
typeof true; // boolean
typeof Symbol(); // symbol
typeof function () {}; // function
typeof {}; // object
null
typeof null; // object!!!
js 中,不同的对象在底层都表示为二进制,在Javascript中二进制前三位都为 0 的话会被检测为 Object 类型,null 的二进制表示全为0,自然前三位也是 0,所以执行 typeof 时会返回 "object"。
**Array, Date, Regexp, Math: **
typeof []; // object
数组的判断不考虑兼容性的话,可以用 Array.isArray() 方法进行检测。
typeof new Date(); // object
typeof /s/g; // object
typeof Math; // object
typeof new String("foo"); // object!!!
typeof new Number(123); // object!!!
typeof new Boolean(true); // object!!!
typeof new Function(""); // function
typeof new Error(); // object
基于以上,基本类型大部分都能被准确检测并返回正确的字符串,并不是所有的类型都能被正确检测出来。所以在实际应用中,避免用基本包装类型 new Number()
这种方式来初始化数据。
三、instanceof 方式
上面说到基本包装类型:new Number(), new Boolean, New String();
它们用 typeof 判断,会检测成对象。那针对基本包装类型可以用 instanceof 来判断。
instanceof 运算符可以用来检测某个构造函数的 prototype 属性是否存在于另外一个要检测对象的原型链上。
// 定义构造函数 function Person(){} var person1 = new Person(); // 因为 Object.getPrototypeOf(person1) === Person.prototype person1 instanceof Person; // true 复制代码
现在我们检测一下:
var str = new String('abc'); // 基本包装类型 var strValue = "foo"; strValue instanceof String; // false str instanceof String; // true str instanceof Object; // true [] instanceof Array; // true [] instanceof Object; // true 复制代码
如果我们修改构造函数的原型后,这个方法也不怎么靠谱了:
var str = new String('abc'); str.__proto__ = Object.prototype; str instanceof String; // false !!! str instanceof Object; // true 复制代码
四、toString() 方式
ECMAScript 的 Boolean 值、数字和字符串的原始值的有趣之处在于它们是伪对象,这意味着它们实际上具有属性和方法。
ECMAScript 定义所有对象都有 toString() 方法,无论它是伪对象,还是真对象。因为 String 类型属于伪对象,所以它一定有 toString() 方法。
使用 Object.prototype.toString
方法, 可以获取到变量的准确的数据类型.
Object.prototype.toString.call(1); // '[object Number]' Object.prototype.toString.call('1'); // '[object String]' Object.prototype.toString.call(NaN); // '[object Number]' Object.prototype.toString.call(foo); // '[object Function]' Object.prototype.toString.call(Symbol()); // "[object Symbol]" Object.prototype.toString.call([1,2,3]); // '[object Array]' Object.prototype.toString.call(undefined); // '[object Undefined]' Object.prototype.toString.call(null); // '[object Null]' Object.prototype.toString.call(true); // '[object Boolean]' Object.prototype.toString.call(/^s/g); // '[object RegExp]' Object.prototype.toString.call(Math); // "[object Math]" Object.prototype.toString.call(new Error()); // "[object Error]" Object.prototype.toString.call(new Date()); // "[object Date]" 复制代码
toString 就能解决基本包装类型的检测错误和 instanceof
的检测不安全。
基于 toString 我们可以构造很多 工具 函数用来检测数据类型,这一块实现的方案很多,本文就按下不表。
五、应用场景
js 类型检测常见的应用场景: 应用场景:添加默认值
function foo(a, b) { // 方式一 if (typeof b=== 'undefined') { b = 0; } // 方式二:不适用foo(10, false)这种情况 b = b || 0; } foo(10); 复制代码
回调函数调用
function fn(callback) { //typeof callback === 'function' ? callback() : null; callback && callback(); } fn(function () { }); 复制代码
还有一个很常见的应用场景当然是后台返回数据的类型的检测了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 重学JS: 数据类型及类型检测
- js类型检测的几种方式盘点
- 前端基本功:JavaScript 的七种数据类型与数据类型检测的4种方法
- 攻击者是如何将PHP Phar包伪装成图像以绕过文件类型检测的
- JavaScript系列--类型判断的4种基本方法,研究jquery的type方法,空对象的检测方法,类数组对象
- 恶意软件如何绕过AMSI检测以逃避检测
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java Web服务:构建与运行
Martin Kalin / 任增刚 / 电子工业出版社 / 2009年11月 / 45.00元
本书以示例驱动的方式详尽地介绍了XML Web服务(JAX-WS)和RESTful Web服务(JAX-RS)二者所涵盖的Java相关API。 《Java Web服务:构建和运行》这本书以清晰、务实的方法讲述Web服务相关技术,提供了混合性的架构总结、完全可以运行的代码示例,以及编译、部署和执行应用程序的一些短小精悍的指令。学习本书,读者将掌握如何从零开始编写Web服务或将已有的服务整合到现......一起来看看 《Java Web服务:构建与运行》 这本书的介绍吧!