关于 JavaScript 中 null 的一切
原文作者:Dmitri Pavlutin
译者:Gopal
JavaScript 有两种类型:原始类型(strings, booleans, numbers, symbols)和对象
对象是一个复杂的数据结构。最简单的 JavaScript 对象是普通对象 —— 键和相关值的集合
let myObject = {
name: 'Eric Cartman'
};
但是很多情况下不能创建一个对象。在这种情况下,JavaScript 提供了一个特殊的值 null —— 表示缺少对象
let myObject = null;
在这篇文章中,你将学习关于 JavaScript 中的 null 的一切: 它的含义,如何检测它,null 和 undefined 之间的区别,以及为什么大量使用 null 会造成代码维护困难等
1.null 的概念
JavaScript 规范中这么描述 null
null 是一种原始类型,表示有意不包含任何对象值
如果您看到 null(分配给变量或由函数返回),那么在那个位置原本应该是一个对象,但由于某种原因,一个对象没有创建
比如,函数 greetObject() 创建对象,但也可以在无法创建对象时返回 null:
function greetObject(who) {
if (!who) {
return null;
}
return { message: `Hello, ${who}!` };
}
greetObject('Eric'); // => { message: 'Hello, Eric!' }
greetObject(); // => null
当上面的函数中传入一个字符串参数时,如预期的,函数返回一个对象 { message: 'Hello, Eric!' }
但是,函数中不传任何参数时,该函数返回 null。返回 null 是合理的,因为 who 参数没有值,导致 greeting 对象无法创建
1.1 null 的一个比较贴切的比喻
考虑关于 null 的一个比较贴切的比喻,你可以把变量想象成一个盒子。就像变量可以容纳对象一样,盒子也可以容纳像茶壶等的物品
但一旦你收到一个盒子,打开它,什么也没有!有人弄错了,给了你一个空盒子。该盒子不包含任何内容,或者换句话说,它包含一个 null 值
2. 如何去检测 null
检查 null 好方法是使用严格相等运算符
const missingObject = null;
const existingObject = { message: 'Hello!' };
missingObject === null; // => true
existingObject === null; // => false
missingObject === null 的结果为 true,因为 missingObject 变量包含一个 null 值。如果变量包含非空值,比如对象,则表达式 existingObject === null 的结果为 false
2.1 null 是一个假值
null 与 false、0、"、undefined、NaN 都是假值。如果在条件语句中遇到它们,那么 JavaScript 将把它们强制为 false
Boolean(null); // => false
if (null) {
console.log('null is truthy');
} else {
console.log('null is falsy'); // logs 'null is falsy'
}
2.2 typeof null
typeof value 类型操作符可以确定值的类型。例如,类型为 15 的是 number,typeof { prop: 'Value' } 等于 object。
有趣的是,null 值类型的结果是什么
typeof null; // => 'object'
一个缺失的对象类型怎么被判断为 object? 原来 typoef null 作为 object 是早期 JavaScript 实现中的一个错误
不要使用 typeof 操作符检测 null 值。如前所述,使用严格的相等运算符 myVar === null
如果你想使用 typeof 去检查一个变量是否是一个对象,你必须排除掉 null 的情况
function isObject(object) {
return typeof object === 'object' && object !== null;
}
isObject({ prop: 'Value' }); // => true
isObject(15); // => false
isObject(null); // => false
3. null 的陷阱
null 通常会在你希望使用对象的情况下意外出现。然后,如果尝试从 null 中提取属性,JavaScript 会抛出一个错误
让我们再次使用 greetObject() 函数并尝试从返回的对象中访问 message 属性
let who = '';
greetObject(who).message;
// throws "TypeError: greetObject() is null"
因为 who 变量是一个空字符串,所以函数返回 null。当从 null 访问 message 属性时,将抛出类型错误错误
你可以通过使用 可选链操作符 来处理 null
let who = '';
greetObject(who)?.message ?? 'Hello, Stranger!';
// => 'Hello, Stranger!'
或者使用下一节中描述的两种选择。
4. null 的替代方案
当你不能构造一个对象时,很容易返回 null。但这种做法也有缺点
一旦 null 出现在执行堆栈中,你总是必须检查它
我们尽量避免返回 null:
- 返回默认对象而不是
null - 抛出错误而不是返回
null
让我们回忆一下 greetObject() 函数返回 greeting 对象
当缺少参数时,可以返回一个默认对象,而不是返回 null
function greetObject(who) {
if (!who) {
who = 'Stranger';
}
return { message: `Hello, ${who}!` };
}
greetObject('Eric'); // => { message: 'Hello, Eric!' }
greetObject(); // => { message: 'Hello, Stranger!' }
或者抛出一个错误
function greetObject(who) {
if (!who) {
throw new Error('"who" argument is missing');
}
return { message: `Hello, ${who}!` };
}
greetObject('Eric'); // => { message: 'Hello, Eric!' }
greetObject(); // => throws an error
这些实践可以让你完全避免处理 null
5. null vs undefined
undefined 就是未初始化的变量或对象属性的值
例如,如果在声明变量时没有赋初值,那么访问该变量的结果为 undefined
let myVariable;
myVariable; // => undefined
null 和 undefined 之间的主要区别是,null 表示丢失了的对象,而 undefined 表示未初始化的状态
严格相等运算符 === 区分 null 和 undefined
null === undefined; // => false
而松散相等运算符 == 则认为 null 和 undefined 相等
null == undefined; // => true
我使用松散相等运算符检查变量是否为 null 或 undefined
function isEmpty(value) {
return value == null;
}
isEmpty(42); // => false
isEmpty({ prop: 'Value' }); // => false
isEmpty(null); // => true
isEmpty(undefined); // => true
6. 总结
null 是 JavaScript 中的一个特殊值,表示丢失的对象
严格相等运算符判断变量是否为空: variable === null。
typoef 操作符用于确定变量的类型(number, string, boolean)。但是,typeof 在 null 情况下会引起误解: typeof null 结果为 object
null 和 undefined 在某种程度上是等价的,但null 表示一个丢失的对象,而 undefined 表示未初始化状态
尽可能避免返回 null 或将变量设置为 null。因为这种做法会导致 null 值的扩展和需要对 null 的验证。相反,尝试使用具有默认属性的对象,或者甚至抛出错误会是更好的实践
你会使用什么方法来检查 null?
关于 JavaScript 中 null 的一切的更多相关文章
- JavaScript中Null和Undefined的深渊
探索JavaScript中Null和Undefined的深渊 当讨论JavaScript中的原始数据类型时,大多数人都知道的基本知识,从String,Number到Boolean.这些原始类型相当简单 ...
- JavaScript中 null 的 typeof是object
JavaScript中 null 的 typeof是object
- Javascript 中 null、NaN和undefined的区别
1.类型分析: js中的数据类型有undefined,boolean,number,string,object等5种,前4种为原始类型,第5种为引用类型. 代码 var a1; var a2 = tr ...
- JavaScript中null和undefined
JavaScript的数据类型大体分为两类:原始类型和对象类型.其中,原始类型包括数字.字符串和布尔值.此外,JavaScript中还有两个特殊的原始值:null(空)和undefined(未定义), ...
- 探索JavaScript中Null和Undefined的深渊
当讨论JavaScript中的原始数据类型时,大多数人都知道的基本知识,从String,Number到Boolean.这些原始类型相当简单,行为符合常识.但是,本文将更多聚焦独特的原始数据类型Null ...
- Javascript中null值,特别注意的两点
null 是一个javascript字面量,表示空值,就是没有对象被呈现.他是javascript原始值之一.null值常被放在期望一个对象上,但是不引用任何对象的参数位置,也就是说对象的初始化. 我 ...
- JavaScript中null和undefined的总结
先说null,它表示一个特殊值,常用来描述“空值”.对null执行typeof运算,结果返回字符串“object”,也就是说,可以将null认为是一个特殊的对象值,含义是“非对象”(感觉怪怪的).实际 ...
- JavaScript中Null和undefind区别
公众号原文 Javascript有5种基本类型:Boolean,Number,Null,Undefined,String:和一种复杂类型:Object(对象): undefined:只有一个值,及特殊 ...
- 【JS】JavaScript中Null和undefind区别
1.undefined:只有一个值,及特殊的undefined.在使用var声明变量但未对其初始化时,这个变量的值是undefined,简言之,undefined就是表示变量申明了但未初始化时的值. ...
随机推荐
- nifi从入门到实战(保姆级教程)——身份认证
上一篇我们搭建好了nifi的运行环境了 但是每次登陆那一串随机字符串的用户名和密码是不是让人很头疼,那是人类能记住的吗?当然不是!!!! 那么今天我们就来消灭这些难看又难记的字符串. windows( ...
- js烧脑面试题大赏
本文精选了20多道具有一定迷惑性的js题,主要考察的是类型判断.作用域.this指向.原型.事件循环等知识点,每道题都配有笔者详细傻瓜式的解析,偏向于初学者,大佬请随意. 第1题 let a = 1 ...
- 超 Nice 的表格响应式布局小技巧
今天,遇到了一个很有意思的问题,一名群友问我,仅仅使用 CSS,能否实现这样一种响应式的布局效果: 简单解析一下效果: 在屏幕视口较为宽时,表现为一个整体 Table 的样式 而当屏幕视口宽度较小时, ...
- python基础教程:定义类创建实例
类的定义 在Python中,类通过class关键字定义,类名以大写字母开头 >>>class Person(object): #所有的类都是从object类继承 pass #pass ...
- 动态树 — Euler_Tour_Tree
一般提到动态树,我们会不约而同的想到 LCT,这算是比较通用,实用,能力较为广泛的一种写法了.当然,掌握 LCT 就需要熟悉掌握 Splay 和各种操作和知识.ETT(中文常用称呼:欧拉游览树)是一种 ...
- Solution -「Luogu 5170」类欧几里得算法
推柿子大赛了属于是. 题目要求三个柿子,不妨分别记为: \[\begin {align} f (a, b, c, n) &= \sum \limits _{i = 0} ^{n} \lfloo ...
- day02_基本语法
基本语法 学习目标: 1. 数据类型 2. 变量 3. 编码介绍 4. 标识符和关键字 5. 字符串类型 6. 数据类型转化 7. 进制转换 8. 运算符 一.数据类型 什么是数据类型? 在开发软件的 ...
- Nginx常用命令之启动与重启
1.测试新的Nginx程序是否正确 [test@P-SH-Nginx-01 nginx]$ ./sbin/nginx -t nginx: the configuration file /usr/loc ...
- Docker非root用户使用
Docker 用户管理 安装Docker后docker相关命令都需要加上sudo才能执行,这里为特定用户添加下权限 Docker群组 不过一般安好docker后该群组已创建 sudo groupadd ...
- 60行从零开始自己动手写FutureTask是什么体验?
前言 在并发编程当中我们最常见的需求就是启动一个线程执行一个函数去完成我们的需求,而在这种需求当中,我们常常需要函数有返回值.比如我们需要同一个非常大的数组当中数据的和,让每一个线程求某一个区间内部的 ...