博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS专题之数据类型和类型检测
阅读量:6584 次
发布时间:2019-06-24

本文共 4753 字,大约阅读时间需要 15 分钟。

本文共 1750 字,读完只需 7 分钟

数据类型有哪些?

ECMAScript 的数据类型分为简单数据类型(也被称为基本数据类型,原始数据类型):

  1. Undefined
  2. Null
  3. String
  4. Number
  5. Boolean

在 ES6 中新增一个简单数据类型 Symbol,所以简单数据类型总共有 6 个,还有复杂数据类型(也叫作引用数据类型):Object。

所有 js 中所有的值最终都将是以上 7 种数据类型之一。

基本数据类型

基本数据类型是保存在的数据结构中的,是按值访问的,基本数据类型的值不会变 (值本身无法被改变) 数据之间进行的是它们的比较。

看代码:

var a,b;a = "jay_chou";b = a;console.log(a);  // jay_chouconsole.log(b);  // jay_choua = "coldplay";  // 改变 a 的值,并不影响 b 的值console.log(a);   // coldplayconsole.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; // truea === c; // false复制代码

一、为什么要进行类型检测?

JavaScript 是动态语言,动态语言和静态语言的区别在于:类型是在编译时检查(静态)还是在运行时检查(动态)。

基于动态类型的特点,如果不注意进行类型检测,JS 很容易在运行代码发生才发现报错。

举个列子:

函数在定义时,参数可以是任何类型,但是函数在实际运行的时候,传入的实参可能是其他同事函数的返回值,也可能是后台的返回值,假如不符合代码逻辑里要求的数据类型,那么就会报错导致 bug 影响程序运行。

因此,我们不光要做类型检测,也应该给自己的函数注释好参数类型和返回值类型,还要和后端定义好接口数据类型格式。

当比较的两个值的类型不同的时候 == 运算符会进行类型转换,但是当两个值的类型相同的时候,即使是 == 也相当于是 ===;=== 在比较两个值的时候,还会比较值的数据类型。

二、typeof 方式

typeof 的返回值总是字符串,字符串的可能值有:

  1. undefined
  2. boolean
  3. number
  4. string
  5. symbol
  6. object
  7. 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.prototypeperson1 instanceof Person;  // true复制代码

现在我们检测一下:

var str = new String('abc');  // 基本包装类型var strValue = "foo";strValue instanceof String;  // falsestr instanceof String;  // truestr 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 是动态语言,数据类型的检查是在运行时执行,为了避免代码莫名其妙报错,所以做好数据类型的检测很有必要。

欢迎关注我的个人公众号“谢南波”,专注分享原创文章。

掘金专栏 JavaScript 系列文章

转载地址:http://ouano.baihongyu.com/

你可能感兴趣的文章
你可能不知道的技术细节:存储过程参数传递的影响
查看>>
.htaccess 基础教程(四)Apache RewriteCond 规则参数
查看>>
多年前写的一个ASP.NET网站管理系统,到现在有些公司在用
查看>>
Docker 部署 SpringBoot 项目整合 Redis 镜像做访问计数Demo
查看>>
React Native 0.20官方入门教程
查看>>
最优化问题中黄金分割法的代码
查看>>
Jquery获取iframe中的元素
查看>>
Laravel 学习笔记5.3之 Query Builder 源码解析(下)
查看>>
Struts2简单入门实例
查看>>
2012CSDN年度博客之星评选http://vote.blog.csdn.net/item/blogstar/xyz_lmn
查看>>
SpringBoot实战总汇--详解
查看>>
尝试使用iReport4.7(基于Ubuntu Desktop 12.04 LTS)
查看>>
子元素应该margin-top为何会影响父元素【转】
查看>>
AJAX 状态值(readyState)与状态码(status)详解
查看>>
BZOJ3668:[NOI2014]起床困难综合症(贪心)
查看>>
LightOJ 1245(Harmonic Number (II))
查看>>
小知识记录
查看>>
图片转流
查看>>
HTML 标签说明
查看>>
java笔记八:IO流之字符流与字符缓冲流
查看>>