一、为什么JS有两个表示“无”的值
JS不同于其他语言,它有2个表示“无”的值,undefined和null。JS在设计上部分参考了Java,为什么JS需要两个值表示“无”,而Java只需要一个?
1995年JS诞生之初与Java类似,只设置了null表示“无”。但Java是静态类型语言,如果一个基本数据类型变量只声明不赋值,编译器会报错,基本数据类型必须有一个该数据类型初值(基础数据类型分配内存,存储的是当前的值),基本数据类型不会为“空”;如果声明一个引用数据类型,但是不确定值是多少可以用null表示(引用类型变量分配了内存,存放的是地址空间)。JS和Java类似数据类型分成基本类型primitive和合成类型complex(对象类型)。但是JS是动态类型语言,声明变量的时候并不会涉及类型,当前变量为空,可能是基本类型也可能是对象类型。“无”值为空对象这种设计在JS中不适用。
JS为动态类型语言,可以出现“无”值的情况有两种,一种是变量声明了但是没有赋值,不知道值是什么;另一种情况是此处的值确定就是没有。JS需要加以区分,因此需要两个表示“无”的值。
notice:此处是个人理解。
二、null与undefined的区别
null和undefined在JS中都表示“无”,他们有什么相似之处又有什么区别呢?
1.相同点
- undefined和null在if语句中会被自动转化为false。
- Boolean(nudefined)和Boolean(null)结果为false。
- 都可使用可选链判空。
2.不同点
-
定义不同
- undefined表示“缺少值”,就是此处应该有一个值,但是还没有定义,被转化为数值是为NaN。
- null表示“没有对象”,即此处不应该有值,被转化为数值时是0。
-
使用场景不同
-
null的使用场景
- 作为函数的参数,表示该函数的参数不是对象。
- 作为对象原型链的终点。
-
undefined的使用场景
- 变量被声明了,但没有赋值时就等于undefined。
- 调用函数时,应该提供的参数没有提供,改参数等于undefined。
- 对象没有赋值的属性,该属性的值为undefined。
- 函数没有返回值时,默认返回undefined。(是异常导致的没有返回值,还是本来该函数就无返回值,并不确定)
-
notice:
- undefined==null的结果为ture,undefined===null为false。undefined是Undefined类型,null为Null类型。undefined和null值相等但是类型不同。
- null表明了此处无值的预期,作用类似于一个占位符。undefined表示不知道此处的值是什么,但是可能是有值的。因此JS中必须以编程的方式将一个值设置为null,但是申明一个变量不赋初值该变量就是undefined。
二、null与undefined之间的坑点
null和undefined在JS中都表示“无”,虽然我们已经知道他们的相同点和区别了,但是使用的时候还是傻傻分不清楚。每个人的编码风格也不太一样,维护的项目历史代码的写法也是千奇百怪。下面的坑你见过几个?
坑点一:判空
- null==undefined的结果为ture,null!=undefined的结果为false。
- null===nudefined的结果为false,null!==undefined的结果为ture。
- typeof null=='undefined'和typeof null==='undefined'的结果为false。
private getLineHeight = () => {
// 有可能传入0
if (this.props.lineHeight === undefined) {
return 18;
}
return this.props.lineHeight;
};
render() {
return (
<View>
{typeof this.props.price !== 'undefined' && (
<Text>this.props.price</Text>
)}
</View>
);
}
-
易踩坑场景举例:
- 仅仅针对为undefined或者null的场景进行判空。
坑点二:对象默认值
-
对象结构可以指定默认值,但是如果结构的对象是null,则默认值不生效。
const {x=3}={x:null}
-
易踩坑场景举例:
- 前端为成员变量兜底了默认值,服务端下发对象包含赋值为null的成员变量,该兜底值不会生效。
- 工程中为某个对象的成员变量赋值为null,调用处为该成员变量设置了兜底默认值。多人开发信息不协调的场景。
坑点三:函数参数默认值
- 如果传入函数实参是null,形参设置的默认兜底值将不生效。
getPositiveNumbers=(numberArray: number[] = []) => {
const positiveNumberArray = [];
for (let i = 0; i < numberArray.length; i++) {
if (numberArray[i] > 0) {
positiveNumberArray.push(numberArray[i]);
}
}
return positiveNumberArray;
};
-
易踩坑场景举例:
- 直接透传服务端下发数据,将服务端下发的数据作为实参传递给函数,但是服务端下发的数据为null