第十五节:各种逻辑运算符总结(&&、||、?、??、&&=、||=、??=)
一. 各种运算符
1 . && 逻辑与
含义:形如 x && y, x为ture的时候,返回y 或者 执行y (y可能是表达式,也可能是函数),否则返回 x 。
PS:除了 0、空字符串" "、NaN、false、null、undefined以外,都为 ture 。
{ console.log("----------------1.&& 逻辑与-------------------"); // 之前的写法 let msg1 = "ypf"; let msg2 = 0; let msg3 = ""; msg1 = msg1 && "default value"; msg2 = msg2 && "default value"; msg3 = msg3 && "default value"; console.log(msg1); //ypf console.log(msg2); //0 console.log(msg3); //空字符串"" }
2. || 逻辑或
含义:形如 x || y, 左侧x为false时返回y 或者 执行y (y可能是表达式,也可能是函数),否则返回x。
注意:如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。 比如 ' '、0、NaN、false,都认为是flase,不符合实际情况,是有bug的。(null 和 undefined认为是false是正常的)
{ console.log("---------------- 2. || 逻辑或-------------------"); // 先看一下||的弊端吧, 下面4种情况,都想原样输出,而不是输出默认值 console.log("" || "default value"); //default value console.log(0 || "default value"); //default value console.log(NaN || "default value"); //default value console.log(false || "default value"); //default value let msg1 = "ypf"; let msg2 = 0; let msg3 = ""; msg1 = msg1 || "default value"; msg2 = msg2 || "default value"; msg3 = msg3 || "default value"; console.log(msg1); //ypf console.log(msg2); //default value 【0的bug】 console.log(msg3); //default value 【空“”的bug】 }
3. 可选链 ? 【ES11-ES2020】
(1). 背景:
多层级的对象时,调用内层的属性或方法,需要加前置校验,判断是否存在,否则会导致程序报错,中断,无法执行下面的业务。
(2). 可选链的符号:?
(3). 可选链的用法:可选链中的 ? 表示【如果问号左边表达式有值, 就会继续查询问号后面的字段, 如果没有值,不会报错,返回undefined】
A. 对象中使用:调用属性和方法
PS:对于方法而言,注意一下下面的两种写法的含义的区别
console.log(userInfo?.myChild2?.getMsg()); //undefined (表示当userInfo存在且myChild2存在的时候调用getMsg())
console.log(userInfo?.myChild2?.getMsg?.()); //undefined (和上边有区别,这里表示当userInfo存在且myChild2存在且getMsg存在的时候才调用)
B. 数组中使用
C. 与空值运算符一起使用
注意:可选链不能用于赋值!!!!!!!
{ console.log( "---------------- 3. 可选链 ? 【ES11-ES2020】-------------------" ); const userInfo = { name: "ypf", age: 18, getMsg() { return "hello world"; }, myChild: { cName: "lmr", cAge: 10, getMsg() { return "hello ypf"; }, }, }; // 一. 之前写法 //1. 想获取myChild中的cAge属性和getMsg方法,需要这么写 const cAge = userInfo && userInfo.myChild && userInfo.myChild.cAge; const cMsg = userInfo && userInfo.myChild && userInfo.myChild.getMsg(); console.log(cAge); console.log(cMsg); //2. 想获取myChild2中的cHeight属性 和 getMsg()方法【实际上并没有myChild2】 //下面这种写法直接报错,并且会导致后续的代码不能运行 // TypeError: Cannot read properties of undefined (reading 'cHeight') /* { const cHeight = userInfo.myChild2.cHeight; console.log(cHeight); } */ // 所以我们就得这样写:获取的是cHeight,我们就需要判断到它的上一级是否存在,即myChild2 // 结果:由于myChild2不存在, 所以无法进if内部,所以不影响后续代码 if (userInfo && userInfo.myChild2) { console.log(userInfo.myChild2.cHeight); } if (userInfo && userInfo.myChild2) { userInfo.myChild2.getMsg(); } // 当然我们也可以这样写 // 结果:输出都是undefined,但不影响后续运行 console.log(userInfo && userInfo.myChild2 && userInfo.myChild2.cHeight); console.log(userInfo && userInfo.myChild2 && userInfo.myChild2.getMsg()); // 二. ES11中的写法 console.log("------------------ES11中的写法-----------------------------"); //1. 想获取myChild中的cAge属性和getMsg方法,需要这么写 【对象中存在】 console.log(userInfo?.myChild?.cAge); //10 console.log(userInfo?.myChild?.getMsg()); //hello ypf //2. 想获取myChild2中的cHeight属性 和 getMsg()方法【实际上并没有myChild2】 console.log(userInfo?.myChild2?.cHeight); //undefined (表示当userInfo存在且myChild2存在的时候调用cHeight) console.log(userInfo?.myChild2?.getMsg()); //undefined (表示当userInfo存在且myChild2存在的时候调用getMsg()) console.log(userInfo?.myChild2?.getMsg?.()); //undefined (和上边有区别,这里表示当userInfo存在且myChild2存在且getMsg存在的时候才调用) // 3. 数组中使用 // 数组中使用(不常见,因为直接arr[42]也是undefined) let arr = [1, 2, 3]; console.log(arr[42]); // undefined console.log(arr?.[42]); // undefined // 4. 与空值运算符??一起使用 let customer = { name: "ypf", }; console.log(customer?.city ?? "青岛"); // "青岛" // 5. 可选链不能用于赋值 // { // let obj1 = {}; // obj1?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment // } console.log("--------------执行完毕----------------"); }
4. 空值合并运算符?? 【ES11-ES2020】
(1) 背景:
解决了之前逻辑或操作符(||)的几个弊端:
||的含义:左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。
比如为假值(例如'',0,NaN,false)时
(2). 符号: ??
(3). 用法:当左侧的操作数为 null或者undefined时,返回其右侧操作数,否则返回左侧操作数。
{ console.log("----------------4. 空值运算符【符号:?】-----------------"); // 先看一下||的弊端吧, 下面4种情况,都想原样输出,而不是输出默认值 console.log("" || "default value"); //default value console.log(0 || "default value"); //default value console.log(NaN || "default value"); //default value console.log(false || "default value"); //default value // 同样上面的情况,再来看一下空值运算符?? 都是原样输出了,达到目的了 console.log("" ?? "default value"); //空字符串"" console.log(0 ?? "default value"); //0 console.log(NaN ?? "default value"); //NaN console.log(false ?? "default value"); //false // 针对null 和 undefined, || 的结果,走的都是默认值,达到目的了 console.log(null || "default value"); //default value console.log(undefined || "default value"); //default value // 针对null 和 undefined, ?? 的结果,走的都是默认值,达到目的了 console.log(null ?? "default value"); //default value console.log(undefined ?? "default value"); //default value // 除了null和undefined外,??的结果都是本身 console.log(1 ?? "default value"); //1 console.log("msg" ?? "default value"); //"msg" console.log(["ypf1", "ypf2"] ?? "default value"); //["ypf1", "ypf2"] }
5. ||= 逻辑或赋值运算 【ES12-ES2021】
含义: 形如 x ||= y 运算仅在 x 为false时,返回右侧的值y,否则仍然返回值x, 实际上可以认为它是 x||(x=y) 的缩写,所以 ||= 也存在一下意外的bug,比如:0、“”、NaN、false,都认为是false,都会执行 ||= 右侧的代码
PS:针对null 和 undefined,执行右侧代码这是我们所需要的,是正确的。
{ console.log("----------------5. ||= 逻辑或赋值运算-------------------"); let msg1 = "ypf"; let msg2 = 0; let msg3 = ""; msg1 = msg1 || "default value"; msg2 = msg2 || "default value"; msg3 = msg3 || "default value"; console.log(msg1); //ypf console.log(msg2); //default value 【0的bug】 console.log(msg3); //default value 【空“”的bug】 // 上述写法等价于 let msg11 = "ypf"; let msg22 = 0; let msg33 = ""; msg11 ||= "default value"; msg22 ||= "default value"; msg33 ||= "default value"; console.log(msg11); //ypf console.log(msg22); //default value 【0的bug】 console.log(msg33); //default value 【空“”的bug】 }
6. &&= 逻辑与赋值运算 【ES12-ES2021】
含义:形如 x &&= y 运算仅在 x 为ture时,返回右侧的值y,否则仍然返回值x, 实际上可以认为它是 x && (x=y) 的缩写
PS:除了 0、“”、NaN、false、null、undefined以外,都为ture
{ console.log("----------------6. &&= 逻辑与赋值运算-------------------"); // 之前的写法 let msg1 = "ypf"; let msg2 = 0; let msg3 = ""; msg1 = msg1 && "default value"; msg2 = msg2 && "default value"; msg3 = msg3 && "default value"; console.log(msg1); //ypf console.log(msg2); //0 console.log(msg3); //空字符串"" // 上述写法等价于 let msg11 = "ypf"; let msg22 = 0; let msg33 = ""; msg11 &&= "default value"; msg22 &&= "default value"; msg33 &&= "default value"; console.log(msg11); //ypf console.log(msg22); //0 console.log(msg33); //空字符串"" }
7. ??= 逻辑空赋值运算符 【ES12-ES2021】
含义:形如 x ??= y 运算仅在 x 为null或undefined时,返回右侧的值y,否则仍然返回值x, 实际上可以认为它是 x ?? (x=y) 的缩写
{ console.log("----------------7. ??= 逻辑空赋值运算-------------------"); // 之前的写法 let msg1 = "ypf"; let msg2 = 0; let msg3 = ""; let msg4 = null; let msg5 = undefined; msg1 = msg1 ?? "default value"; msg2 = msg2 ?? "default value"; msg3 = msg3 ?? "default value"; msg4 = msg4 ?? "default value"; msg5 = msg5 ?? "default value"; console.log(msg1); //ypf console.log(msg2); //0 console.log(msg3); //空字符串"" console.log(msg4); //"default value"; console.log(msg5); //"default value"; // 上述写法等价于 let msg11 = "ypf"; let msg22 = 0; let msg33 = ""; let msg44 = null; let msg55 = undefined; msg11 ??= "default value"; msg22 ??= "default value"; msg33 ??= "default value"; msg44 ??= "default value"; msg55 ??= "default value"; console.log(msg11); //ypf console.log(msg22); //0 console.log(msg33); //空字符串"" console.log(msg44); //"default value"; console.log(msg55); //"default value"; }
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。