许多编程语言都有一个称为null的非值。它指示一个变量当前不指向一个对象,例如,当它还没有初始化的时候。
德城ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为成都创新互联公司的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:18980820575(备注:SSL证书合作)期待与您的合作!
相比之下,JavaScript有两个这样的非值:undefined和null。在这篇博文中,我们将研究它们有什么不同,以及如何最好地使用或避免它们。
这两种值非常相似,经常互换使用。因此,它们的区别是微妙的。
ECMAScript语言规范对其描述如下。
在JavaScript中拥有两个非值现在被认为是一个设计错误(甚至被JavaScript的创造者Brendan Eich认为)。
那为什么不从 JavaScript 中删除其中的一个值呢?JavaScript 的一个核心原则是绝不破坏向后兼容。这个原则有很多好处。它最大的缺点是,设计上的错误无法被删除。
在Java中(它启发了JavaScript的许多方面),初始化值取决于变量的静态类型。
在JavaScript中,每个变量都可以容纳对象值和基本类型值。因此,如果null意味着 "不是一个对象",那么JavaScript也需要一个初始化值,意味着 "既不是一个对象也不是一个原始值"。这个初始化值就是 undefined。
如果一个变量myVar还没有被初始化,它的值是undefined。
- let myVar;
- assert.equal(myVar, undefined);
如果一个属性.unknownProp丢失,访问该属性会产生undefined的值。
- const obj = {};
- assert.equal(obj.unknownProp, undefined);
如果一个函数有一个没有参数的返回语句,该函数隐含地返回undefined。
- function myFunc() {
- return;
- }
- assert.equal(myFunc(), undefined);
如果一个参数x被省略了,语言将该参数初始化为undefined。
- function myFunc() {
- return;
- }
- assert.equal(myFunc(), undefined);
- myFunc();
通过obj?.someProp的可选链路,如果obj未定义或为空,则返回未定义。
- > undefined?.someProp
- undefined
- > null?.someProp
- undefined
一个对象的原型要么是一个对象,要么在原型链的末端是null。Object.prototype没有原型。
- > Object.getPrototypeOf(Object.prototype)
- null
如果我们将一个正则表达式(如/a/)与一个字符串(如'x')相匹配,我们要么得到一个带有匹配数据的对象(如果匹配成功),要么得到空(如果匹配失败)。
- > /a/.exec('x')
- null
JSON数据格式不支持undefined,只支持null。
- > JSON.stringify({a: undefined, b: null})
- '{"b":null}'
在以下情况下,将使用参数默认值。
例如:
- function myFunc(arg='abc') {
- return arg;
- }
- assert.equal(myFunc('hello'), 'hello');
- assert.equal(myFunc(), 'abc');
- assert.equal(myFunc(undefined), 'abc');
undefined也触发了参数的默认值,这说明它是一个元值。
下面的例子说明了这一点的用处。
- function concat(str1='', str2='') {
- return str1 + str2;
- }
- function twice(str) { // (A)
- return concat(str, str);
- }
在A行,我们没有为str指定一个参数默认值。当这个参数缺失时,我们把这个状态转发给concat(),让它选择一个默认值。
解构中的缺省值与参数缺省值的工作原理类似--如果一个变量在数据中没有匹配,或者它与undefined的变量匹配,就会使用它们。
- const [a='a'] = [];
- assert.equal(a, 'a');
- const [b='b'] = [undefined];
- assert.equal(b, 'b');
- const {prop: c='c'} = {};
- assert.equal(c, 'c');
- const {prop: d='d'} = {prop: undefined};
- assert.equal(d, 'd');
当通过 value?.prop 进行可选的链接时
- function getProp(value) {
- // optional static property access
- return value?.prop;
- }
- assert.equal(
- getProp({prop: 123}), 123);
- assert.equal(
- getProp(undefined), undefined);
- assert.equal(
- getProp(null), undefined);
下面两个操作的效果类似。
- obj?.[«expr»] // optional dynamic property access
- func?.(«arg0», «arg1») // optional function or method call
nullish 合并算子??如果一个值undefined或为null,则允许我们使用默认值:
- > undefined ?? 'default value'
- 'default value'
- > null ?? 'default value'
- 'default value'
- > 0 ?? 'default value'
- 0
- > 123 ?? 'default value'
- 123
- > '' ?? 'default value'
- ''
- > 'abc' ?? 'default value'
- 'abc'
null合并赋值操作符??=:
- function setName(obj) {
- obj.name ??= '(Unnamed)';
- return obj;
- }
- assert.deepEqual(
- setName({}),
- {name: '(Unnamed)'}
- );
- assert.deepEqual(
- setName({name: undefined}),
- {name: '(Unnamed)'}
- );
- assert.deepEqual(
- setName({name: null}),
- {name: '(Unnamed)'}
- );
- assert.deepEqual(
- setName({name: 'Jane'}),
- {name: 'Jane'}
- );
下面分享一下我们自己的代码中处理undefined 和null的最常见方法。
举例,我们可能希望一个属性file.title永远存在,并且永远是一个字符串。有两种常见的方法来实现这一点。
这里,只检查undefined和null,而不检查一个值是否是字符串。你必须自己决定是否要把它作为一个额外的安全措施来实施。
如下所示
- function createFile(title) {
- if (title === undefined || title === null) {
- throw new Error('`title` must not be nullish');
- }
- // ···
- }
为什么选择这种方法?
我们想把undefined和null当作一样的东西,因为JavaScript代码经常这样做--比如说。
- // 检测一个属性是否存在
- if (!obj.requiredProp) {
- obj.requiredProp = 123;
- }
- const myValue = myParameter ?? 'some default';
如果我们的代码中出现了问题,出现了undefined或null,我们希望它尽可能快地失败。
如下所示
- function createFile(title) {
- title ??= '(Untitled)';
- // ···
- }
我们不能在这里使用参数缺省值,因为它只由undefined 触发。相反,我们依靠nullish 合并赋值运算符??=。
为什么选择这种方法?
例如,我们可能希望一个属性file.title是一个字符串或 "关闭"(文件没有标题)。有几种方法可以实现这一点。
- function createFile(title) {
- if (title === undefined) {
- throw new Error('`title` must not be undefined');
- }
- return {title};
- }
另外,undefined可以触发一个默认值。
- function createFile(title = '(Untitled)') {
- return {title};
- }
为什么选择这种方法?
- function createFile(title) {
- if (title === null) {
- throw new Error('`title` must not be null');
- }
- return {title};
- }
为什么选择这种方法?
当接收一个值时,把undefined和null都当作 "不是一个值 "是有意义的。然而,当我们创建值时,我们希望不含糊,以便处理这些值时保持简单。
这指向了一种不同的方法。如果我们需要一个 "关闭"的值,但又不想使用undefined或null作为这样的值,怎么办?请往下看。
我们可以创建一个特殊的值,每当属性.title被关闭时,我们就使用这个值。
- const UNTITLED = Symbol('UNTITLED');
- const file = {
- title: UNTITLED,
- };
空对象模式来自于面向对象的编程。
在下面的例子中,UntitledFile实现了 "null" 模式。
- // 抽象的超类
- class File {
- constructor(content) {
- if (new.target === File) {
- throw new Error('Can’t instantiate this class');
- }
- this.content = content;
- }
- }
- class TitledFile extends File {
- constructor(content, title) {
- super(content);
- this.title = title;
- }
- getTitle() {
- return this.title;
- }
- }
- class UntitledFile extends File {
- constructor(content) {
- super(content);
- }
- getTitle() {
- return '(Untitled)';
- }
- }
- const files = [
- new TitledFile('Dear diary!', 'My Diary'),
- new UntitledFile('Reminder: pick a title!'),
- ];
- assert.deepEqual(
- files.map(f => f.getTitle()),
- [
- 'My Diary',
- '(Untitled)',
- ]);
我们也可以只对标题使用空对象模式(而不是对整个文件对象)。
Maybe 类型是一种函数编程技术。
- function getTitle(file) {
- switch (file.title.kind) {
- case 'just':
- return file.title.value;
- case 'nothing':
- return '(Untitled)';
- default:
- throw new Error();
- }
- }
- const files = [
- {
- title: {kind: 'just', value: 'My Diary'},
- content: 'Dear diary!',
- },
- {
- title: {kind: 'nothing'},
- content: 'Reminder: pick a title!',
- },
- ];
- assert.deepEqual(
- files.map(f => getTitle(f)),
- [
- 'My Diary',
- '(Untitled)',
- ]);
我们可以通过Arrays对 "just "和 "nothing "进行编码。我们的方法的好处是,它得到了TypeScript的良好支持(通过判别性联合)。
我不喜欢用undefined作为 "关闭 "的值,有三个原因。
因此,如果我需要一个特殊的值,我会使用以下两种方法中的一种。
作者:Michael Thiessen
译者:前端小智
来源:dev原文:https://2ality.com/2021/01/undefined-null-revisited.html
当前题目:5年前,学习Null和Undefined,现在有了新的认知,看看这位人才怎么说?
网页链接:http://www.shufengxianlan.com/qtweb/news33/407883.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联