js类型判断 判断Null和Undefined
javaScript中判断数据类型的方法主要有三种:
**typeof:**原理是通过根据变量的机器码来判断
instanceof:根据 构造函数的 prototype
属性是否出现在某个实例对象的原型链上
typeof
序号 | 类型 | 结果 |
1 | Undefined | “undefined” |
2 | Null | “object” |
3 | Boolean | “boolean” |
4 | Number | “number” |
5 | BigInt(ECMAScript 2020 新增) | “bigint” |
6 | String | “string” |
7 | Symbol (ECMAScript 2015 新增) | “symbol” |
8 | Function 对象 (按照 ECMA-262 规范实现 [[Call]]) | “function” |
9 | 任何对象(Array) | “object” |
10 | 宿主对象(由 JS 环境提供) | 取决于具体实现 |
这里有两个地方需要注意
- 第一个是
typeof null
的结果是"object"
javaSctript在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息:
- 000:对象
- 010:浮点数
- 100:字符串
- 110:布尔
- 1:整数
null
:所有机器码均为0
undefined
:用 −2^30 整数来表示
所以,typeof
在判断 null
的时候就出现问题了,由于 null
的所有机器码均为0,因此直接被当做了对象来看待。
- 还有就是表中最后一条,宿主对象(由 JS 环境提供)的结果是取决于具体情况
instanceof
- 用于检测构造函数的
prototype
属性是否出现在某个实例对象的原型链上,所以instanceof 判断的是对象的实例,理解这一点非常关键
let simpleStr = "This is a simple string";
simpleStr instanceof String; // 返回 false, 非对象实例,因此返回 false
let str = String('aa')
str instanceof Object // false
'aaa' instanceof Object // false
- 正确的使用方法,只能判断通过new创建的字符串,也是instanceof 的缺陷
let myString = new String();
let newStr = new String("String created with constructor");
let myDate = new Date();
let myObj = {};
myString instanceof String; // 返回 true
newStr instanceof String; // 返回 true
myDate instanceof Object; // 返回 true
myObj instanceof Object; // 返回 true, 尽管原型没有定义
({}) instanceof Object; // 返回 true, 同上
- 只能判断实例对象是否h在某一条原型链上,而不能直接判断实例对象是什么类型
// Object.getPrototypeOf( o ) === Object.prototype,因为这几个对象都是在Object的原型链上,所以都是true
Array instanceof Object // true
Function instanceof Object // true
String instanceof Object // true
Date instanceof Object // true
RegExp instanceof Object // true
Reflect instanceof Object // true
...
- 如果要
instanceof
判断变量l类型,一般要具体到某一变量类型,不能判断unll和undefined
// 判断是否是函数
function fn(){}
fn instanceof Function // true
let fn2 = ()=>{};
fn2 instanceof Function // true
// 判断是否是对象
({}) instanceof Object // true
// 判断是否是数组
[] instanceof Array // true
let list = new Array
list instanceof Array // true
// 判断是否是字符串
let str = 'aaa'
str instanceof Object // false,str不是String 的实例
let str = new String()
str instanceof String // true
// 判断哪是否是null
null instanceof null // 报错 Uncaught TypeError: Right-hand side of 'instanceof' is not an object
// 判断是否是undefined
undefined instanceof undefined // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
- 判断存在继承关系的对象实例
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
var mycar = new Car("Honda", "Accord", 1998);
var a = mycar instanceof Car; // 返回 true
var b = mycar instanceof Object; // 返回 true
Object.prototype.toString
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('hi') // "[object String]"
Object.prototype.toString.call({a:'hi'}) // "[object Object]"
Object.prototype.toString.call([1,'a']) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"
总结:
typeof 和instanceof的缺点
- typeof:
判断null的结果为“object”,是jasascript诞生就存在的bug - instanceof:
1、判断null 和undefined 的时候会报错
2、在判断字符串的时候,如果不是通过new 方式创建的字符串,得到的结果为fasle
let str = 'this is string; str instanceof String'
接口为fasle
3、如果更改了对象的原型,那么得到结果也是不准确的
var o = new C();
o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype
C.prototype = {};
o instanceof C; // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.
需要注意的是,如果表达式 obj instanceof Foo
返回 true
,则并不意味着该表达式会永远返回 true
,因为 Foo.prototype
属性的值有可能会改变,改变之后的值很有可能不存在于 obj
的原型链上,这时原表达式的值就会成为 false
。另外一种情况下,原表达式的值也会改变,就是改变对象 obj
的原型链的情况,虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的 __proto__
伪属性,是可以实现的。比如执行 obj.__proto__ = {}
之后,obj instanceof Foo
就会返回 false
了。
typeof 和instanceof的使用场景
- typoof和instanceof 都无法判断Null ,我们需要通过其他方式判断null
// null 与自己比较,总是返回
null === null // true
// typeof exp != "undefined" 排除了 undefined
function isNull(value) {
if (!value && typeof value != "undefined" && value != 0) {
return true;
} else {
return false;
}
}
- typeof 可以判断
undefined,而 instanceof
,判断会报错
undefined === undefined // true
typeof undefined // "undefined"
undefined instanceof undefined // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
- typeof 无法判断
Array 和Object
,instanceof 可以
typeof [] // "object"
function fn(){};
fn instanceof Function // true
- type 判断
undefined 和null
的区别(两个变量类型之间)
typeof undefined // "undefined"
typeof null // "object"
// undefined 和 null 之间要又 三等运算符
undefined == null // true
undefined === null // false
undefined != null // false
undefined !== null // true