一些有用的 js 快捷运算:可选链操作符、空值合并操作符、空值赋值运算符、非空断言操作符、扩展和剩余运算符、解构

自学JavaScript第六天- 一些有用的 js 快捷运算:可选链操作符、空值合并操作符、空值赋值运算符、非空断言操作符、扩展和剩余运算符、解构

  • 可选链操作符(`?.`)
  • 空值合并操作符(`??`)
  • 空值赋值运算符(`??=`)
  • 非空断言操作符(`!.`)
  • 扩展和剩余运算符(`...`)
    • 扩展运算
    • 剩余运算
  • 解构
    • 数组解构
    • 对象的解构

js 有一些很方便的快捷运算符,类似于三元表达式,用的好了可以非常方便的简化代码

可选链操作符(?.)

读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。如果某一引用无效(nullundefined)不会引起错误,而是返回 undefined

const a = {id:1, name:'张三'};
console.log(a?.age);

// 多个可选链
let res = a?.name?.firstName;
// 可选链表达式
let res = a?.['na' + 'me'];
// 访问数组
let arrItem = arr?.[13];

简化判断对象是否包含某一成员,如果包含访问该成员的某些属性或方法。

空值合并操作符(??)

空值合并操作符是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。它与逻辑或操作符类似,但是某些情况下(例如左侧值为 '' 即空字符串,或数字 0,或布尔值 false),会意外的返回右侧操作数。而空值合并操作符只有在左侧为空(null 或者 undefined)时返回右侧。

let a = 0 || 123;	// 123
let a = 0 ?? 123;	// 0
let a = false ?? 123;	// false

简化某些可能需要与 0 或 false 等合并时进行的判断,减少意外。也可以和可选链合用,达成访问属性为空时返回默认值的操作。

let a = person?.name ?? '匿名';

空值赋值运算符(??=)

类似于空值合并操作符,在运算符左侧为空( null 或者 undefined ) 时,将右侧赋值给左侧

let b = 'hello';
let a = 0;
let c = null;
a ??= b;	// a === 0
c ??= b;	// c === 'hello'

非空断言操作符(!.)

这是TypeScript的语法,叫非空断言操作符**(non-null assertion operator)**,和?.相反,这个符号表示对象后面的属性一定不是null或undefined。

let a = {id:1, name='张三'};
console.log(a!.id)

扩展和剩余运算符(...)

在 js 中,扩展运算符**(spread)和剩余运算符(rest)均是三个点(...)**。

扩展运算

扩展运算主要作用是将数组或对象拆分为多个参数序列,它会调用默认的 Iterator 接口

// 扩展数组
const test = (a, b, c) => {
	console.log(a)		// 1
	console.log(b)		// 2
	console.log(c)		// 3
}

let arr = [1, 2, 3];
test(...arr);

// 将一个数组扩展到另一个数组中
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5];	 	// [1, 2, 3, 4, 5]
let arr3 = [4, ...arr1, 5];		// [4, 1, 2, 3, 5]	

// 将字符串扩展为数组
let str = 'hello';
let arr4 = [...str];	// ['h', 'e', 'l', 'l', 'o']

扩展运算也适用于对象

let a = {id:1, name='张三'};
let b = {...a};

使用对象的扩展和直接赋值是有区别的,直接赋值其实是将原对象的内存地址引用进行赋值,而扩展某种程度上是创建了一个新对象。需注意扩展并不完全等同于深度复制,因为扩展只是将一级属性进行复制,如果其中有对象的话,还是赋值此对象的内存地址引用。

剩余运算

剩余运算和扩展运算正好相反,是将一个值序列组合合并成一个数组

// 当函数参数个数不固定,可以使用剩余运算合并成一个数组
const f1 = (...args) => {
	console.log(args)		// [1, 2, 3]
}
f1(1, 2, 3);

// 部分参数不固定
const f2 = (item, ...args) => {
	console.log(item)		// 1
	console.log(args)		// [2, 3]
}
f2(1, 2, 3);

解构

解构也有叫做拆包,就是将一个对象(或数组,因为js中数组也是对象)拆分开来。

数组解构

let arr = [1, 2, 3];
// 将数组元素依次赋值给单个变量
let [a, b, c] = arr;	// 相当于 a=1,b=2,c=3
// 变量个数小于数组元素个数无影响
let [a, b] = arr;
// 变量个数大于数组元素个数,多出来的赋值为 undefined
let [a, b, c, d] = arr;		// d为undefined
// 解构时也可以使用默认值
let [a, b, c = 33, d = 44] = arr;	// c的值还是3,d的值是44
// 只取部分元素可以使用占位
let [, b] = arr;	// b为2
let [a, ...b] = arr;	// 配合剩余运算, a为1,b为[2,3]

需要注意的是,扩展运算符(剩余运算) ... 只能出现在解构语法的最后。

对象的解构

对象解构时,必须名称一致,对顺序可以没有要求。

let obj = {a: 1, b: 2};
let {x, y} = obj;	// x和y均为 undefined
let {a, b} = obj; 	// a为1,b为2
let {b, a} = obj;	// 同上

对象的解构中,还能为变量重命名

let obj = {a: 1, b: 2};
let {a: x, b: y} = obj;
// a , b 会报未定义的错
// x为1,y为2

配合扩展运算符获取对象部分属性

let obj = {a: 1, b: 2, c: 3};
let {a, ...b} = obj;
// a为1
// b为{b: 2, c: 3}

使用已有变量进行解构

let x, y;
({a: x, b: y} = {a: 1, b: 2, c: 3});
// x为1
// y为2

需注意的是,因为 {} 中的内容会被部分浏览器当成一个代码块,所以需要使用 () 括号包裹

对象的解构使用默认值

let x, y, z;
({a: x, b: y, d: z = {num: 1}} = {a: 1, b: 2, c: 3});
// x为1
// y为2
// z为 {num: 1}

你可能感兴趣的:(javascript,前端)