三目運算子 ?:
每到週末我都會問自己,怎麼安排?於是我寫了個程式跑了一下
if (hasMoney) {
console.log('週末嗨翻天');
} else {
console.log('週末睡一天');
}
複製程式碼
看上去沒有什麼問題,但總感覺程式碼有點臃腫,能不能稍微簡約一點?
換成三目運算子後
hasMoney ? console.log('週末嗨翻天') : console.log('週末睡一天');
複製程式碼
look,當hasMoney為true的時候,嗨翻天,為false的時候的睡一天。這種操作符在我們的根據簡單的判斷條件賦值的時候非常有用
let weekendPlan = hasMoney ? '週末嗨翻天' : '週末睡一天';
複製程式碼
如此,我們的程式碼就不會充斥著大量的if判斷條件句,還能略顯騷氣。但是,別騷過度了
val = simpleCondition
? 1
: simpleConditionAgain
? 2
: simpleConditionAgainAndAgain
? 3
: 4;
複製程式碼
上面的例子有點為了裝逼而裝逼的感覺,在程式碼可讀性方面有點糟糕,即使換成了if條件句也不甚美觀;像這種情況,可以使用switch語句或者策略模式的設計思想優化。
邏輯與操作符 &&
如果有錢的話,週末就去嗨翻天,但沒錢的情況還沒有想好要幹嘛(雖然沒錢的情況幹不了什麼),常規操作為
if (hasMoney) {
console.log('週末嗨翻天');
}
複製程式碼
這個時候使用三目運算子改寫的話
hasMoney ? console.log('週末嗨翻天') : undefined;
複製程式碼
有點奇怪,我們不得不寫個undefined去告訴程式判斷條件為false的時候應該怎麼做。使用邏輯與操作符就可以避免這個問題
hasMoney && console.log('週末嗨翻天');
複製程式碼
邏輯與操作符會使用Boolean函式判斷每一個條件(表示式)是否為true,當所有的判斷條件都為true的情況下,就會返回最後的表示式的運算結果;但是如果有判斷條件為false的話,就會返回第一個判斷條件為false的運算結果
true && console.log('It is true'); // It is true
true && false && console.log('It is true'); // 返回 false
true && 0 && console.log('It is true'); // 返回 0
true && undefined == null && console.log('It is true'); // It is true, 表示式undefined == null的運算結果為true
true && undefined === null && console.log('It is true'); // 返回 false, 表示式undefined === null的運算結果為false
複製程式碼
所以在react中使用邏輯與操作符渲染元素的時候,一定要注意
render() {
return (
<Fragment>{
data.length && data.map(item => <span>{ item }</span>)
}</Fragment>
);
}
// 當沒有資料的時候,頁面會渲染出一個0
複製程式碼
上面的例子的本意是當有資料的時候就將資料渲染出來,沒有資料的時候,不做任何操作。但是邏輯與操作符會將第一個為false的表示式的運算結果返回,導致返回了個0!
邏輯或操作符 ||
說到邏輯與操作符,就不得不提它的好基友:邏輯或操作符。考慮下面的場景
// 當自身為undefined時,賦值為0,否則還是賦值為自身
val = val !== undefined ? val : 0;
複製程式碼
使用三目運算子去處理上述例子的邏輯時,我們需要顯式的判斷val是否為空的,然後再決定變數val是否應該等於本身。那麼本著能省就省的原則,我們可以使用邏輯或操作符
val = val || 0;
複製程式碼
邏輯或操作符,其會將第一個表示式的運算結果傳入Boolean函式,如果Boolean函式返回true,就會返回這個運算結果;否則將會嘗試下一個,直到結束;如果所有的表示式的運算結果對應的布林值都為false,則返回最後一個表示式的運算結果
故此操作符在向下相容、設定函式引數的預設值時非常有用
// ES5設定函式預設值
function testFunc(arg1) {
arg1 = arg1 || 1;
// do something else
}
let a = 1,
b = 2,
c = null;
console.log(a || b || c); // 1
console.log(0 || b || c); // 2
console.log(0 || false || c); // null
複製程式碼
note: 故此猜想,if條件句裡面使用邏輯或、邏輯與操作符,實際上也只是返回表示式的運算結果,然後再隱式呼叫了Boolean函式得到一個最終的布林值
邏輯取反 !
上文說到,有錢的週末可以為所欲為,沒錢的週末,估計也就只能選擇睡一天了。這種情況下,如果使用hasMoney作為判斷標準,我們的程式碼是這樣的
hasMoney === false && console.log('週末睡一天');
複製程式碼
當hasMoney不是一個布林值的時候,hasMoney === false語句就會一直返回false,造成有錢的假象。所以我們必須的將hasMoney轉換成一個布林值才能判斷,恰好取反操作符可以同時給我們做這兩件事
!hasMoney && console.log('週末睡一天');
複製程式碼
這樣就能在沒錢的時候睡一天了。
取反操作符能夠將一個非Boolean型別的值轉化為Boolean型別的值且取反
!true && console.log('666'); // 返回false
!!true && console.log('666'); // 666
{} && console.log('666'); // 報錯
!{} && console.log('666'); // 返回false
!!{} && console.log('666'); // 666
複製程式碼
按位取反操作符 ~
加入我們需要判斷一個陣列裡面是否存在某個元素,在ES6裡面可以使用includes
let arr = ['we', 'are', 'the', 'BlackGold', 'team'];
arr.includes('the') && console.log('in'); // in
複製程式碼
但是這個方法有比較大的限制:沒辦法傳入一個篩選函式。
let arr = ['we', 'are', 'the', 'BlackGold', 'team'];
arr.includes(element => element === 'the') && console.log('in'); // 返回false
複製程式碼
這種情況下,我們通常可以使用findIndex方法
let arr = ['we', 'are', 'the', 'BlackGold', 'team'];
arr.findIndex(element => element === 'the') !== -1 && console.log('in'); // in
複製程式碼
由於findIndex方法返回的索引是從0開始的,所以我們必須得判斷其返回的索引是否不等於-1或者是大於等於0。如果使用按位取反操作符,將不需要顯示去判斷
let arr = ['we', 'are', 'the', 'BlackGold', 'team'];
~arr.findIndex(element => element === 'we') && console.log('in'); // in
~arr.findIndex(element => element === 'the') && console.log('in'); // in
複製程式碼
按位取反操作符,顧名思義,就是將變數的每一個位元位取反:0->1、1->0
console.log(~-1); // 0 轉換為Boolean值即為false
console.log(~0); // -1 轉換為Boolean值即為true
console.log(~1); // -2 轉換為Boolean值即為true
複製程式碼
結語
JavaScript騷操作系列主要總結JavaScript一些好用的特性、方法,以供交流學習之用,不喜勿噴。如有錯漏,歡迎指正。
相關文章:
@Author: PaperCrane