一、数据类型介绍
在 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] }); }