数据类型检测
说明
js数据类型、typeof、instanceof和Object.prototype.toString、包装类型笔记总结
# js数据类型
基本数据类型与引用数据类型
ECMAScript 有 7 种基本数据类型(也称为原始类型):
- Undefined
- Null
- Boolean
- Number
- String
- Symbol
- BigInt
还有一种引用数据类型叫 Object(对 象)。因为在 ECMAScript 中不能定义自己的数据类型,所有值都可 以用上述 8 种数据类型之一来表示。
基本数据类型:基础类型存储在栈内存,被引用或拷贝时,会创建一个完全相等的变量;占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储。
Undefined
、Null
、Boolean
、Number
、String
、Symbol
和BigInt
;引用数据类型:引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
Object、Array、RegExp、Date、Math、Function
# typeof操作符
typeof
会返回一个变量的基本数据类型的字符串表达
其中数组、对象、null都会被判断为object,其他判断都正确。
ES6 的 typeof 是如何对待函数和对象类型的:
- 如果一个对象(Object)没有实现 [[Call]] 内部方法,那么它就返回 object
- 如果一个对象(Object)实现了 [[Call]] 内部方法,那么它就返回 function
- 相应地,如果一个函数对象支持了内部的 [[Construct]] 方法,那么它就可以使用 new 或 super 来调用,这时我们就可以把这个函数对象称为:构造函数。
typeof 1 // 'number'
typeof NaN // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
let a = BigInt(0);
typeof a // 'bigint'
typeof null // 'object'
typeof [] // 'object'
typeof {} // 'object'
typeof console // 'object'
typeof window // "object"
typeof console.log // 'function'
typeof Object // function
function f() {}
typeof f // 'function'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
null
的类型是object
,这是由于历史原因造成的。1995年的 JavaScript 语言第一版,只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),没考虑null
,只把它当作object
的一种特殊值。后来null
独立出来,作为一种单独的数据类型,为了兼容以前的代码,typeof null
返回object
就没法改变了
undefined 代表的含义是未定义,null 代表的含义是空对象。一般变量声明了但还没有定义的时候会返回 undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化
console.log(Boolean(undefined)); // false
console.log(Boolean(null)); // false
console.log(Number(undefined)); // NaN
console.log(Number(null)); // 0
console.log(isNaN(undefined)); // true
console.log(isNaN(null)); // false
2
3
4
5
6
如果我们想要判断一个变量是否存在,可以使用typeof
(不能使用if(a)
, 若a
未声明,则报错)
if(typeof a != 'undefined'){
//变量存在
}
2
3
# instanceof操作符
instanceof 可以准确地判断引用数据类型,但是不能正确判断基础数据类型,返回一个布尔值
2 instanceof Number // false
true instanceof Boolean // false
'str' instanceof string // false
var o = {};
var a = [];
function f() {}
f instanceof Function // true
a instanceof Array // true
o instanceof Object // true
a instanceof Object // true
f instanceof Object // true
2
3
4
5
6
7
8
9
10
11
12
13
14
15
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上
// 定义构建函数
let Car = function() {}
let benz = new Car()
benz instanceof Car // true
let car = new String('xxx')
car instanceof String // true
let str = 'xxx'
str instanceof String // false
2
3
4
5
6
7
8
9
# instanceof实现原理
function myInstanceof(left, right) {
// 这里先用typeof来判断基础数据类型,如果是,直接返回false
if(typeof left !== 'object' || left === null) return false;
// getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(left);
while(true) {
if(proto === null) return false;
if(proto === right.prototype) return true;//找到相同原型对象,返回true
proto = Object.getPrototypeof(proto);
}
}
2
3
4
5
6
7
8
9
10
11
# Object.prototype.toString
通用检测数据类型
toString是Object的原型方法,Array、function等类型作为Object的实例,都重写了toString方法,因此在想要得到对象的具体类型时,应该调用Object原型上的toString方法
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('1') // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(function(){}) // "[object Function]"
Object.prototype.toString.call(null) //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(/123/g) //"[object RegExp]"
Object.prototype.toString.call(new Date()) //"[object Date]"
Object.prototype.toString.call([]) //"[object Array]"
Object.prototype.toString.call(document) //"[object HTMLDocument]"
Object.prototype.toString.call(window) //"[object Window]"
const obj = {
title: "devpoint",
toString() {
return "myobj";
},
};
console.log(String(obj)); // myobj
let a = {
i: 1,
toString() {
return this.i++
}
}
console.log(a==1); // true
console.log(a==2); // true
console.log(a); // {i: 3, toString: ƒ}
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
# constructor
有两个作用,一是判断数据的类型,二是对象实例通过 constructor 对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,就不能用来判断数据类型了
console.log((2).constructor === Number); // true
console.log(false.constructor === Boolean); // true
console.log([].constructor === Array); // true
console.log(function(){}.constructor === Object); // false
console.log({}.constructor === Object); // true
--------------------------------------------------
function fn() {}
fn.prototype = new Array()
let f = new fn()
console.log(f.constructor === fn); // false
console.log(f.constructor === Array); // true
console.log(f instanceof Array); // true
2
3
4
5
6
7
8
9
10
11
12
13
# JS包装类型
在 JavaScript 中,基本类型是没有属性和方法的,但是为了便于操作基本类型的值,在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象
Number()
Number 是对应数值的引用类型。要创建一个 Number 对象,就使用 Number 构造函数并传入一个 数值
布尔值,true 转换为 1,false 转换为 0
null,返回 0
undefined,返回 NaN。
字符串,如果是空字符串,则返回 0。 如果字符串包含字母,则返回 NaN
Number
方法的参数是对象时,将返回NaN
,除非是包含单个数值的数组
console.log(Number(null)); // 0 console.log(Number(undefined)); // NaN console.log(Number([])); // 0 console.log(Number({})); // NaN console.log(Number('100hc')); // NaN console.log(Number("")); // 0
```js console.log(new String("aa") instanceof String); // true console.log(String("haha")==="haha"); // true console.log(new String("haha")==="haha"); // false console.log(new String("haha")===new String("haha")); // false
console.log(Boolean(false) === false); // true console.log(Boolean(false) === Boolean(false)); // true console.log(new Boolean(false) === new Boolean(false)); // false
## 数值转换
<img src="./assets/image-20230523140810779.png" alt="image-20230523140810779" style="zoom:150%;" />
```js
console.log(!!'false'); // true
console.log(!!'true'); // true
console.log(!!' '); // true
console.log(!!''); // false
console.log(!!100); // true
console.log(!!-100); // true
console.log(!!Infinity); // true
console.log(!!0); // false
console.log(!!NaN); // false
console.log(NaN != NaN); // true
console.log(NaN == NaN); // false
function fn() {}
console.log([]==false); // true
console.log([]==true); // false
console.log({}==false); // false
console.log({}==true); // false
console.log(!![]); // true
console.log(!!{}); // true
console.log(!!fn); // true
console.log(!!null); // false
console.log(!!undefined); // false
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
# 参考
MDN Web Docs (mozilla.org) (opens new window)
JavaScript高级程序设计(第4版)