JavaScript数据类型全解:编写通用函数,精准判断各种数据类型

一、数据类型介绍

在 JavaScript 规范中,共定义了七种数据类型,分为 “基本类型” 和 “引用类型” 两大类,如下所示:

  • 基本类型:String、Number、Boolean、Symbol、Undefined、Null

  • 引用类型:Object

下面将详细介绍这七种数据类型的一些特性。

1、String 类型

String 类型用于表示由零或多个 16 位 Unicode 字符组成的字符序列,即字符串 。

2、Number 类型

JavaScript 中的数字类型只有 Number 一种,Number 类型采用 IEEE754 标准中的 “双精度浮点数” 来表示一个数字,不区分整数和浮点数 。

3、Boolean 类型

Boolean 类型只有两个字面值:true 和 false 。 在 JavaScript 中,所有类型的值都可以转化为与 Boolean 等价的值。

转化规则如下:

  • 所有对象都被当作 true
  • 空字符串被当作 false
  • null 和 undefined 被当作 false
  • 数字 0 和 NaN 被当作 false
4、Symbol 类型

Symbol 是 ES6 新增的一种原始数据类型,它的字面意思是:符号、标记。代表独一无二的值 。

在 ES6 之前,对象的属性名只能是字符串,这样会导致一个问题,当通过 mixin 模式为对象注入新属性的时候,就可能会和原来的属性名产生冲突 。而在 ES6 中,Symbol 类型也可以作为对象属性名,凡是属性名是 Symbol 类型的,就都是独一无二的,可以保证不会与其他属性名产生冲突。

5、Undefined 类型

Undefined 是 Javascript 中特殊的原始数据类型,它只有一个值,即 undefined,字面意思是:未定义的值 。它的语义是,希望表示一个变量最原始的状态,而非人为操作的结果 。

这种原始状态会在以下 4 种场景中出现:

【1】声明了一个变量,但没有赋值
var foo;
console.log(foo); //undefined

访问 foo,返回了 undefined,表示这个变量自从声明了以后,就从来没有使用过,也没有定义过任何有效的值,即处于一种原始而不可用的状态。

【2】访问对象上不存在的属性
console.log(Object.foo); // undefined
var arr = [];
console.log(arr[0]); // undefined

访问 Object 对象上的 foo 属性,返回 undefined , 表示Object 上不存在或者没有定义名为 foo 的属性。数组中的元素在内部也属于对象属性,访问下标就等于访问这个属性,返回 undefined ,就表示数组中不存在这个元素。

【3】函数定义了形参,但没有传递实参
// 函数定义了形参 a
function fn(a) {
    console.log(a); //undefined
}
fn(); // 未传递实参

函数 fn 定义了形参 a, 但 fn 被调用时没有传递参数,因此,fn 运行时的参数 a 就是一个原始的、未被赋值的变量。

【4】使用 void 对表达式求值
void 0 ; // undefined
void false; // undefined
void []; // undefined
void null; // undefined
void function fn(){} ; // undefined

ECMAScript 明确规定 void 操作符 对任何表达式求值都返回 undefined ,这和函数执行操作后没有返回值的作用是一样的,JavaScript 中的函数都有返回值,当没有 return 操作时,就默认返回一个原始的状态值,这个值就是 undefined,表明函数的返回值未被定义。

因此,undefined 一般都来自于某个表达式最原始的状态值,不是人为操作的结果。当然,你也可以手动给一个变量赋值 undefined,但这样做没有意义,因为一个变量不赋值就是 undefined 。

6、Null 类型

Null 是 Javascript 中特殊的原始数据类型,它只有一个值,即 null,字面意思是:“空值” 。它的语义是,希望表示一个对象被人为的重置为空对象,而非一个变量最原始的状态 。 null 是原始数据类型 Null 中的唯一一个值,但 typeof 会将 null 误判为 Object 类型 。

7、Object 类型

在 ECMAScript 规范中,引用类型除 Object 本身外,Date、Array、RegExp 也属于引用类型 。

引用类型也即对象类型,ECMA262 把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。 也就是说,对象是一组没有特定顺序的值 。由于其值的大小会改变,所以不能将其存放在栈中,否则会降低变量查询速度。因此,对象的值存储在堆(heap)中,而存储在变量处的值,是一个指针,指向存储对象的内存处,即按址访问。具备这种存储结构的,都可以称之为引用类型 。

二、判断数据类型方法

1、typeof

在 JavaScript 里使用 typeof 来判断数据类型,只能区分基本类型,即 “number”,”string”,”undefined”,”boolean”,”object” 五种。
对于数组、对象来说,其关系错综复杂,使用 typeof 都会统一返回 “object” 字符串。

typeof {} //object

typeof [] //object

要想区别对象、数组单纯使用 typeof 是不行的。或者你会想到 instanceof 方法。

2、instanceof

instanceof是javaScript中的一种运算符,用于判断某个对象是否属于某个类(或其父类)的实例,

console.log({} instanceof Object) //true

console.log([] instanceof Object) //true

console.log(function () {} instanceof Object) //true

上面代码发现都是 Object 的实例

所以要判断复合数据类型,要如下判断:

//对象
({} instanceof Object) && !({} instanceof Function) && !({} instanceof Function)

//数组
([] instanceof Object) && ([] instanceof Array)

//函数
(function () {} instanceof Object) && (function () {} instanceof Function)

虽然 instanceof 运算符在某些情况下可以很方便地判断对象所属的类,但是在实际开发中需要注意其局限性,并结合其他方法和技巧来进行类型判断。

3、Object.prototype.toString.call()

更简便的方式,即是使用 Object.prototype.toString.call() 来确定类型。

由于 JavaScript 中一切都是对象,任何都不例外,对所有值类型应用 Object.prototype.toString.call() 方法

对于 Object.prototype.toString() 方法,会返回一个形如 “[object XXX]” 的字符串。

如果对象的 toString() 方法未被重写,就会返回如上面形式的字符串。

toString()为Object的原型方法,而Array,function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法。

Call是一个允许您更改另一个函数上下文的函数。

对于 Object.prototype.toString.call(arg),若参数为 null 或 undefined,直接返回结果。

若参数不为 null 或 undefined,则将参数转为对象,再作判断。

4、编写一个函数判断所有数据类型
//编写一个函数判断所有数据类型
function _typeof(item) {
    let res = Object.prototype.toString.call(item);
    res = res.split(" ")[1];
    res = res.substr(0, res.length - 1);
    return res;
}

效果如下:

console.log(_typeof(123));//Number

console.log(_typeof("abc"));//String

console.log(_typeof(true));//Boolean

console.log(_typeof(null));//Null

console.log(_typeof(undefined));//Undefined

var fun = function () {}
console.log(_typeof(fun));//Function

var arr = [1, 2, 3]
console.log(_typeof(arr));//Array

var obj = {
    name: 'jack',
    age: 20
}
console.log(_typeof(obj));//Object

三、判断两个数组是否相等

1、将两个数组转成字符串比较, 但是发现他们只是顺序不相等也被当做不相等
[1, 2, 3].toString() == [3, 2, 1].toString();
//  -- --false
2、我们可以先把数组排序按照从小到大的顺序sort() 函数
[1, 2, 3].sort().toString() == [3, 2, 1].sort().toString();
//  -- --true

这样的就是 “1,2,3” == "1,2,3"结果是相等的

3、如果数组里的元素是标量, 非object类型, 可以使用 == 比较数组里的元素:
scalarArrayEquals(array1, array2) {
    return array1.length == array2.length && array1.every(function (v, i) {
        return v === array2[i]
    });
}
  • 32
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邹荣乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值