es6非空判断

示例1

es5

if(value !== null && value !== undefined && value !== ''){
//...
}

es6改进后

if(value??'' !== ''){
//...
}

空值合并运算符

读取对象属性的时候,如果某个属性的值是nullundefined,有时候需要为它们指定默认值。常见做法是通过||运算符指定默认值。

const headerText = response.settings.headerText || 'Hello, world!';
const animationDuration = response.settings.animationDuration || 300;
const showSplashScreen = response.settings.showSplashScreen || true;

上面的三行代码都通过||运算符指定默认值,但是这样写是错的。开发者的原意是,只要属性的值为nullundefined,默认值就会生效,但是属性的值如果为空字符串或false0,默认值也会生效。

??: 空值合并运算符。空值合并运算符将会遍历列表,并返回第一个不是 nullundefined 的值。

举例

null      ?? 'hi'       // 'hi'
undefined ?? 'hey' // 'hey' false ?? 'hola' // false
0 ?? 'bonjour' // 0
'first' ?? 'second' // first

这个运算符的一个目的,就是跟链判断运算符?.配合使用,为nullundefined的值设置默认值。

const animationDuration = response.settings?.animationDuration ?? 300;

上面代码中,如果response.settingsnullundefined,或者response.settings.animationDurationnullundefined,就会返回默认值300。也就是说,这一行代码包括了两级属性的判断。

这个运算符很适合判断函数参数是否赋值。

function Component(props) {
const enable = props.enabled ?? true;
// …

注意

??本质上是逻辑运算,它与其他两个逻辑运算符&&||有一个优先级问题,它们之间的优先级到底孰高孰低。优先级的不同,往往会导致逻辑运算的结果不同。

现在的规则是,如果多个逻辑运算符一起使用,必须用括号表明优先级,否则会报错。

// 报错
lhs && middle ?? rhs
lhs ?? middle && rhs
lhs || middle ?? rhs
lhs ?? middle || rhs

上面四个表达式都会报错,必须加入表明优先级的括号。

(lhs && middle) ?? rhs;
lhs && (middle ?? rhs); (lhs ?? middle) && rhs;
lhs ?? (middle && rhs); (lhs || middle) ?? rhs;
lhs || (middle ?? rhs); (lhs ?? middle) || rhs;
lhs ?? (middle || rhs);

条件判断

es5

if(
type == 1 ||
type == 2 ||
type == 3 ||
type == 4 ||
){
//...
}

es6改进

ES6中数组实例方法includes

const condition = [1,2,3,4];
if( condition.includes(type) ){
//...
}

数组过滤

es5数组过滤一般用filter来实现

const a = [1,2,3,4,5];
const result = a.filter(
item =>{
return item === 3
}
)

es6

const a = [1,2,3,4,5];
const result = a.find(
item =>{
return item === 3
}
)

find性能更加优秀,find方法中找到符合条件的项就不会继续遍历数组。

扁平化数组

一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。

const deps = {
'采购部':[1,2,3],
'人事部':[5,8,12],
'行政部':[5,14,79],
'运输部':[3,64,105],
}
let member = [];
for (let item in deps){
const value = deps[item];
if(Array.isArray(value)){
member = [...member,...value]
}
}
member = [...new Set(member)]

改进后

const deps = {
'采购部':[1,2,3],
'人事部':[5,8,12],
'行政部':[5,14,79],
'运输部':[3,64,105],
}
let member = Object.values(deps).flat(Infinity);

获取对象的全部属性值Object.values。涉及到数组的扁平化处理,用ES6提供的flat方法,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?

取值

取值在程序中非常常见,比如从对象obj中取值。

const obj = {
a:1,
b:2,
c:3,
d:4,
e:5,
} const a = obj.a;
const b = obj.b;
const c = obj.c;
const d = obj.d;
const e = obj.e;

或者

const f = obj.a + obj.d;
const g = obj.c + obj.e;

改进

const {a,b,c,d,e} = obj;
const f = a + d;
const g = c + e;

如果想创建的变量名和对象的属性名不一致,可以这么写:

const {a:a1} = obj;
console.log(a1);// 1

补充

ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefinednull。否则会报错,故要给被解构的对象一个默认值。

const {a,b,c,d,e} = obj || {};

对象取值

let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb" let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined

上面代码的第一个例子,等号左边的两个变量的次序,与等号右边两个同名属性的次序不一致,但是对取值完全没有影响。第二个例子的变量没有对应的同名属性,导致取不到值,最后等于undefined

如果解构失败,变量的值等于undefined

let {foo} = {bar: 'baz'};
foo // undefined

上面代码中,等号右边的对象没有foo属性,所以变量foo取不到值,所以等于undefined

如果变量名与属性名不一致,必须写成下面这样。

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa" let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

这实际上说明,对象的解构赋值是下面形式的简写

let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };

也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
foo // error: foo is not defined

上面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo

与数组一样,解构也可以用于嵌套结构的对象。

let obj = {
p: [
'Hello',
{ y: 'World' }
]
}; let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"

注意,这时p是模式,不是变量,因此不会被赋值。如果p也要作为变量赋值,可以写成下面这样。

let obj = {
p: [
'Hello',
{ y: 'World' }
]
}; let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]

合并数据

es5

const a = [1,2,3];
const b = [1,5,6];
const c = a.concat(b);//[1,2,3,1,5,6] const obj1 = {
a:1,
}
const obj1 = {
b:1,
}
const obj = Object.assgin({}, obj1, obj2);//{a:1,b:1}

改进,考虑去重

const a = [1,2,3];
const b = [1,5,6];
const c = [...new Set([...a,...b])];//[1,2,3,5,6] const obj1 = {
a:1,
}
const obj2 = {
b:1,
}
const obj = {...obj1,...obj2};//{a:1,b:1}

最新文章

  1. DP专辑
  2. Swift: 在Swift中桥接OC文件(自己创建的类文件、第三方库文件)
  3. mysql mysqldump只导出表结构或只导出数据的实现方法
  4. Chrome 浏览器跨域和安全访问问题 使用 chrome的命令行标记:disable-web-security 参数联调线上数据
  5. QNX环境
  6. 使用objdump objcopy查看与修改符号表
  7. 又一道软通动力7K月薪面试题——银行业务调度系统
  8. android自定义控件 onMeasure() 测量尺寸
  9. 基于SOAP的xml网络交互心得
  10. cassandra 数据到Java对象的映射绑定
  11. Opencv在linux下安装
  12. python 中list的深拷贝和浅拷贝
  13. 各数据库连接maven配置
  14. 195. Spring Boot 2.0数据库迁移:Flyway
  15. leetcode739
  16. CloneZilla 恢复系统报错Waiting for device dev/disk/by-id/.....
  17. Windows 7 上面安装 dotnet core 之后 使用 应用报错的处理:api-ms-win-crt-runtime-l1-1-0.dll 丢失
  18. 干了2个月java开发最深的体会
  19. (数据挖掘-入门-3)基于用户的协同过滤之k近邻
  20. cetos7 systemd 详解

热门文章

  1. requests接口自动化-assert断言
  2. P4201-[NOI2008]设计路线【结论,树形dp】
  3. Markdown学习 Day 001
  4. AOJ/树与二叉搜索树习题集
  5. MySQL学习总结:提问式回顾 undo log 相关知识
  6. 9.亿级流量电商系统JVM模型参数预估方案
  7. PostgreSQL 大小写问题 一键修改表名、字段名为小写
  8. 初入CTF(封神榜第一关)
  9. print spooler LPF 打印机漏洞
  10. Visual Studio CMake 项目和 WSL