assert.equal(c, ‘c’);
const {prop: d=‘d’} = {prop: undefined};
assert.equal(d, ‘d’);
4.3 undefined 和 null 以及可选链
当通过 value?.prop
进行可选的链接时
-
如果
value
是undefined
或null
,则返回undefined
。也就是说,只要value.prop
会抛出一个异常,就会发生这种情况。 -
否则,返回
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
4.4 undefined 和 null 和 nullish 聚结
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
的最常见方法。
5.1 undefined 或 null 都不能作为实际值使用
举例,我们可能希望一个属性file.title
永远存在,并且永远是一个字符串。有两种常见的方法来实现这一点。
这里,只检查undefined
和null
,而不检查一个值是否是字符串。你必须自己决定是否要把它作为一个额外的安全措施来实施。
5.1 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
,我们希望它尽可能快地失败。
5.1.2 undefined 和 null 都会触发默认值
如下所示
function createFile(title) {
title ??= ‘(Untitled)’;
// ···
}
我们不能在这里使用参数缺省值,因为它只由undefined
触发。相反,我们依靠nullish 合并赋值运算符??=
。
为什么选择这种方法?
-
我们想把
undefined
和null
同等对待(见上一节)。 -
我们希望我们的代码能够稳健地、无声地处理
undefined
和null
。
5.2 undefined 或 null 都是“关闭”值
例如,我们可能希望一个属性file.title
是一个字符串或 “关闭”(文件没有标题)。有几种方法可以实现这一点。
5.2.1 null是 "关闭的 "值
function createFile(title) {
if (title === undefined) {
throw new Error(‘title
must not be undefined’);
}
return {title};
}
另外,undefined
可以触发一个默认值。
function createFile(title = ‘(Untitled)’) {
return {title};
}
为什么选择这种方法?
-
我们需要一个表示“关闭”的非值。
-
我们不希望我们的非值触发参数默认值和解构默认值。
-
我们想把非值字符串化为JSON(这是我们不能用
undefined
做的)。
5.2.2 undefined 是"关闭的 "值。
function createFile(title) {
if (title === null) {
throw new Error(‘title
must not be null’);
}
return {title};
}
为什么选择这种方法?
-
我们需要一个表示“关闭”的非值。
-
我们确实想让我们的非值触发参数默认值和解构默认值。
5.2.3 为什么不同时使用undefined和null作为 "关闭 "的值?
当接收一个值时,把undefined
和null
都当作 "不是一个值 "是有意义的。然而,当我们创建值时,我们希望不含糊,以便处理这些值时保持简单。
这指向了一种不同的方法。如果我们需要一个 "关闭"的值,但又不想使用undefined
或null
作为这样的值,怎么办?请往下看。
5.3 处理“关闭”的其他方式
5.3.1 特殊值
我们可以创建一个特殊的值,每当属性.title
被关闭时,我们就使用这个值。
const UNTITLED = Symbol(‘UNTITLED’);
const file = {
title: UNTITLED,
};
5.3.2 空对象模式
空对象模式来自于面向对象的编程。
-
一个共同的超类的所有子类都有相同的接口。
-
每个子类都实现了一个实例运行的不同模式。
-
其中一个模式是 “null”。
在下面的例子中,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)’,
]);
我们也可以只对标题使用空对象模式(而不是对整个文件对象)。
5.3.3 Maybe 类型
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’,
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
自学几个月前端,为什么感觉什么都没学到??
这种现象在很多的初学者和自学前端的同学中是比较的常见的。
因为自学走的弯路是比较的多的,会踩很多的坑,学习的过程中是比较的迷茫的。
最重要的是,在学习的过程中,不知道每个部分该学哪些知识点,学到什么程度才算好,学了能做什么。
很多自学的朋友往往都是自己去找资料学习的,资料上有的或许就学到了,资料上没有的或许就没有学到。
这就会给人一个错误的信息就是,我把资料上的学完了,估计也-就差不多的了。
但是真的是这样的吗?非也,因为很多人找的资料就是很基础的。学完了也就是掌握一点基础的东西。分享给你一份前端分析路线,你可以参考。
CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
还有很多的同学在学习的过程中一味的追求学的速度,很快速的刷视频,写了后面忘了前面,最后什么都没有学到,什么都知道,但是什么都不懂,要具体说,也说不出个所以然。
所以学习编程一定要注重实践操作,练习敲代码的时间一定要多余看视频的时间。
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
多人找的资料就是很基础的。学完了也就是掌握一点基础的东西。分享给你一份前端分析路线,你可以参考。
CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
还有很多的同学在学习的过程中一味的追求学的速度,很快速的刷视频,写了后面忘了前面,最后什么都没有学到,什么都知道,但是什么都不懂,要具体说,也说不出个所以然。
所以学习编程一定要注重实践操作,练习敲代码的时间一定要多余看视频的时间。
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算