&& ,|| 超越了我的認(rèn)知
今天的課程誕生于一個(gè) bug,有一段代碼:
- const person = {
- name: 'suyan',
- getName() {
- return this.name;
- }
- };
- function isSuyan()
- if (person.name === 'suyan' && person.getName) {
- return true;
- }
- return false;
- }
隨手對(duì)這段代碼進(jìn)行了重構(gòu):
- function isSuyan()
- return person.name === 'suyan' && person.getName;
- }
執(zhí)行下面打的代碼,結(jié)果是什么?
- let isTrue = isSuyan();
- console.log(isTrue);
結(jié)果是一個(gè)函數(shù),可能出乎你我的意料:
遇到問(wèn)題立馬在百度一下:
看到一段解釋:
Logical operators are typically used with Boolean (logical) values. When they are, they return a Boolean value. However, the && and || operators actually return the value of one of the specified operands, so if these operators are used with non-Boolean values, they will return a non-Boolean value. |
意思:邏輯運(yùn)算符如果使用的都是布爾值,則結(jié)果也是布爾值。然而,在 && 和 || 中, 當(dāng)操作數(shù)是非布爾值的時(shí)候結(jié)果可能是非布爾值。
理解起來(lái)有點(diǎn)繞開(kāi),看個(gè)例子:
&& 運(yùn)算符從左到右進(jìn)行計(jì)算,如果為真,繼續(xù)往后走,直到遇到為 false 的,或者到了最后一個(gè)操作數(shù)。如果操作數(shù)是布爾值結(jié)果返回布爾值,如果操作數(shù)是非布爾值結(jié)果返回非布爾值。
- const a = 10;
- const b = -5;
- const c = 1;
- console.log(a && b); // -5
- console.log(a > 0 && b); // -5
- console.log(a < 0 && b); // false
- console.log(a && b < 0); // true
- console.log(a && b > 0); // false
- console.log(a > 0 && b < 0); // true
- console.log(a && b && c); // 1
|| 運(yùn)算符,只要遇到一個(gè)真值便停止計(jì)算,結(jié)果的規(guī)則和 && 運(yùn)算符一致。
- console.log(a || b); // 10
- console.log(a > 0 || b); // true
- console.log(a < 0 || b); // -5
- console.log(a || b < 0); // 10
- console.log(a || b > 0); // 10
- console.log(a > 0 || b < 0); // true
- console.log(a || b || c); // 10
擴(kuò)散幾個(gè)知識(shí)點(diǎn):
1.可以被轉(zhuǎn)換成 false 的值:null、NaN、0、空字符串 "", '',``、undefined。
2.&& 的優(yōu)先級(jí)大于 || 的優(yōu)先級(jí)。
- true || false && false // returns true, because && is executed first
- (true || false) && false // returns false, because operator precedence cannot apply
3.!和 !! 操作符返回的值永遠(yuǎn)是布爾值,上面的例子可以改為下面這樣,返回值永遠(yuǎn)是布爾值:
- function isSuyan() {
- return !!(person.name === 'suyan' && person.getName);
- }
4. 優(yōu)先級(jí)
假如有個(gè) Label 顯示用戶的名稱,顯示規(guī)則為:默認(rèn)值是前端小課,如果用戶定義了別名就用別名,如果用戶定義了真實(shí)的名字就用真實(shí)的名字,優(yōu)先級(jí)為真實(shí)名字 > 昵稱 > 默認(rèn)名字。我以前這樣寫:
- function showName() {
- let showName;
- let trueName = '真名';
- let nickName = '別名';
- if (trueName) {
- showName = trueName;
- }
- else if (nickName) {
- showName = nickName;
- }
- else {
- showName = '前端小課';
- }
- return showName;
- }
學(xué)完這節(jié)課程我這樣寫,兩個(gè)函數(shù)的結(jié)果是一樣的,但代碼量從 15 行縮減到了 6 行:
- function showName2() {
- let defaultName = '前端小課';
- let trueName = '真名';
- let nickName = '別名';
- return trueName || nickName || defaultName;
- }
這節(jié)課程主要學(xué)習(xí)了 JavaScript 中的 && 、||、! 和 !!,如果使用不當(dāng)可能會(huì)引發(fā)bug。大家加油!!!