JS 【总结】null和undefined区别,你该如何判断正确的类型?

4,035 阅读5分钟

第一:JS 分为哪两大类型?
基本数据类型:按值访问,可操作保存在变量中的实际的值。基本类型值指的是简单的数据段。 基本数据类型有这五种:Undefined、Null、String、Number、Boolean、Symbol。
引用类型:当复制保存着对象的某个变量时,操作的是对象的引用,但在为对象添加属性时,操作的是实际的对象。引用类型值指那些可能为多个值构成的对象。引用类型值指那些可能为多个值构成的对象。
引用类型有这几种:object、Array、RegExp、Date、Function、特殊的基本包装类型(String、Number、Boolean)以及单体内置对象(Global、Math)。
基本类型的变量是存放在栈区的(栈区指内存里的栈内存)栈区包括了 变量的标识符和变量的值。
引用类型的值是按引用访问的。 准确地说,引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针
第二、undefined和null:
两者有相似处:
1、给变量赋值时候,几乎没什么差别;
2、undefinednull在做if判断是都会被自动转为false,相等运算符甚至直接报告两者相等;
但是,如果直接判断的话,结果并不是预想中的:

undefined == false   //false;
null == false    // false;

所以在做判断时,一般都取反

if(!undefined){
     // 此处省略逻辑代码
}
if(!null){
     // 此处省略逻辑代码
}
null == undefined//true

二者区别是:
1、null是一个表示"无"的对象,转为数值时为0;
2、undefined是一个表示"无"的原始值,转为数值时为NaN。

Number(null) //0
Number(undefined) //NaN

3、通过typeof类型检测出来的结果不同:

typeof undefined //undefined;
typeof null // object

4、null表示"没有对象",一个空对象指针,即该处不应该有值。典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
5、undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。

var i;
i // undefined

function f(x){console.log(x)}
f() // undefined

var  o = new Object();
o.p // undefined

var x = f();
x // undefined
// 先判断变量是否存在
if ( (typeof a) == 'undefined') { // 用关键字typeof判断,不存在则是返回undefined字符串
    // 判断已存在变量的值是否为空
    if ( a != undefined && a != null) { // 注意此处undefined是js中的一种类型,不是字符串
    .....
    }
}

接下来再聊聊如何正确判断类型?
说到这里,首先就想到typeof 与 instanceof:
1、typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型;它返回值是一个字符串,该字符串说明运算数的类型。number、string、undefined、boolean、function、object)。

typeof 100; //number
typeof (1==1); //boolean
typeof 'onepixel'; //string
typeof onepixel; // undefined
typeof new Date(); //object
typeof null;//object
-----------------
typeof {} ; //object
typeof [] ; //object
typeof parseInt; // function

2、typeof对于原始类型来说,除了null都可以显示正确类型 typeof对于对象来说,除了函数都会显示object。
3、instanceof用于判断一个变量是否某个对象的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。 在这里需要特别注意的是:instanceof 检测的是原型。
例子:

[] instanceof Array; //true
{} instanceof Object;//true
new Date() instanceof Date;//true
function Person(){};
new Person() instanceof Person;
[] instanceof Object; //true
new Date() instanceof Object;//true
new Person instanceof Object;//true

注意:
1、typeof不能判断变量具体的数据类型比如数组、正则、日期、对象,因为都会返回object,不过可以判断function,如果检测对象是正则表达式的时候,在Safari和Chrome中使用typeof的时候会错误的返回"function",其他的浏览器返回的是object;判断null的时候返回的是一个object,这是js的一个历史遗留问题,判断NaN的时候返回是number。
2、instanceof可以判断出[]是Array的实例,同时也认为是Object的实例,Why????思考?
3、instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。 之后增加了Array.isArray()方法判断这个值是不是数组的。

最后,总结一下:
1、typeof能够检测出了null之外的原型类型(String、Number、Boolean、Undefined),对于对象类型能判断出function、其他的都为Object;
2、判断一个值是否为数组,使用Array.isArray();
3、如果需要判断一个值是否为null,最直接就是与null比较;

value === null;    //true or false

注意这里需要三等号操作符“===”,因为三等号操作符在进行比较的时候不会将变量强制转换为另一种类型。
由此可见,无论是typeof还是instanceof都不能准确判断出正确的类型。 共同点:基本数据类型都可以判断
不同点:instanceof可以判断这个变量是否为某个函数的实例,而typeof不能
用法:typeof经常用来检测一个变量是不是最基本的数据类型,instanceof简单说就是判断一个引用类型的变量具体是不是某种类型的对象。 联系:typeof和instanceof的目的都是检测变量的类型,两个区别在于typeof只能用于检测基本数据类型,instanceof可以检测基本数据类型,也可以检测某些引用数据类型,因为instanceof只能通过true或者false来判断,不能直接看出来是什么类型,所以需要另外一种直观的方法: 解决方案 因为js中的一切都是对象,任何都不例外,对所有值类型应用 Object.prototype.toString.call() 方法结果如下:

console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]

利用这个特性,可以写一个比typeof instanceof更准确的判断方法:

var type = function (o) {
    var s = Object.propertype.toString.call(o)
   return s.match(/object(.∗?)/)[1].toLowerCase()
}
type({}); // "object"
type([]); // "array"
type(5); // "number"
type(null); // "null"
type(); // "undefined"
type(/abcd/); // "regex"
type(new Date()); // "date"