javascript 数据类型、类型检测、类型检测函数的封装(包括纯粹对象、空对象、window 对象)。
一、基础类型及类型检测
1、基础类型
JavaScript 数据类型包括:Null、Undefined、Boolean、Number、String、Symbol、Bigint(7 种原始类型)、Object(引用类型,包括 Object/Array/Date/Function/RegExp 等)
原始类型保存在栈内存。
引用类型保存在堆内存,不可以直接访问堆内存空间中的位置和操作堆内存空间。只能操作对象在栈内存中的引用地址。
引用类型数据在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存中堆内存中的对象。
2、类型检测
(1)、typeof
7 种原始类型可以使用 typeof 操作符检查数据类型(其中,typeof null === ‘object’)
检查 Object 派生出来的结构类型,使用 typeof 是不行的, 会一直 === ‘object’,通常使用 instanceof 检查 Object 种类(这样还是存在误差)。
(2)、instanceof
instanceof 运算符是用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
Tips: 检测对象不是某个构造函数的实例
1 2 3 4 5 6
| if (!(mycar instanceof Car)) { }
if (!mycar instanceof Car) { }
|
(3)、Object.prototype.toString().call()
每个对象都有一个 toString()方法,可以通过 toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为 thisArg。
调用 Object.prototype.toString 会返回一个由 “[object “ 和 class 和 “]” 组成的字符串,而 class 是要判断的对象的内部属性。
(看了别人翻译的es5规范,讲解这个toString()函数,如下:)
当toString方法被调用的时候,执行步骤为:
1、如果 this 值是 undefined,就返回 [object Undefined]
2、如果 this 的值是 null,就返回 [object Null]
3、让 O 成为 ToObject(this) 的结果
4、让 class 成为 O 的内部属性 [[Class]] 的值
5、最后返回由 “[object “ 和 class 和 “]” 三个部分组成的字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| var number = 1; var string = "123"; var boolean = true; var und = undefined; var nul = null; var obj = { a: 1 }; var array = [1, 2, 3]; var date = new Date(); var error = new Error(); var reg = /a/g; var func = function a() {};
function checkType() { for (var i = 0; i < arguments.length; i++) { console.log(Object.prototype.toString.call(arguments[i])); } }
checkType( number, string, boolean, und, nul, obj, array, date, error, reg, func );
console.log(Object.prototype.toString.call(Math)); console.log(Object.prototype.toString.call(JSON));
function a() { console.log(Object.prototype.toString.call(arguments)); } a();
|
(4)、封装一个 type 函数
写一个 type 函数检测各种类型的值,考虑到兼容性(IE6,null 和 undefined 会被 Obejct.prototype.toString 识别为[object Obejct])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var class2type = {};
"Boolean Number String Function Array Date RegExp Object Error" .split(" ") .map(function (item, index) { class2type["[object " + item + "]"] = item.toLowerCase(); });
function type(obj) { if (obj == null) { return obj + ""; } return typeof obj === "object" || typeof obj === "function" ? class2type[Object.prototype.toString.call(obj)] || "object" : typeof obj; }
|
(5)、函数类型的检测
1 2 3 4
| function isFunction(obj) { return type(obj) === "function"; }
|
(6)、纯粹对象的检测
什么是纯粹对象?
该对象是通过 “{}” 或 “new Object” 创建的,该对象含有零个或者多个键值对。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
function isPlainObject(obj) { var proto, Ctor;
if (!obj || toString.call(obj) !== "[object Object]") { return false; }
proto = Object.getPrototypeOf(obj);
if (!proto) { return true; }
Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
return ( typeof Ctor === "function" && hasOwn.toString.call(Ctor) === hasOwn.toString.call(Object) ); }
|
(7)、空对象的判断
1 2 3 4 5 6 7
| function isEmptyObject(obj) { var name; for (name in obj) { return false; } return true; }
|
(8)、window 对象的判断
1 2 3
| function isWindow(obj) { return obj != null && obj === obj.window; }
|
(9)、数组类型的检测
1 2 3 4 5 6
| var isArray = Array.isArray || function (obj) { return type(obj) === "array"; };
|
(10)、类数组的判断
满足的三个条件:
1、是数组
2、长度为 0
3、lengths 属性是大于 0 的数字类型,并且 obj[length - 1]必须存在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function isArrayLike(obj) { var length = !!obj && "length" in obj && obj.length; var typeRes = type(obj);
if (typeRes === "function" || isWindow(obj)) { return false; }
return ( typeRes === "array" || length === 0 || (typeof length === "number" && length > 0 && length - 1 in obj) ); }
|
函数库的实现,如:underscore
1 2 3 4 5 6
| var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var isArrayLike = function (collection) { var length = getLength(collection); return typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX; };
|
(11)、判断是不是 DOM 元素
1 2 3
| var isElement = function (obj) { return !!(obj && obj.nodeType === 1); };
|