PJCHENder 未整理筆記

[JS] JavaScript 運算子(Operator)

2017-10-26

[JS] JavaScript 運算子(Operator)

運算式與運算子 @ MDN

[TOC]

條件判斷(conditional statement)

  • 物件(object): 都是 true(空物件也是 true)
  • 陣列(array):陣列是一種物件,因此都會是 true(空陣列 [] 也是 true)
  • Undefined: 是 false
  • Null:是 false
  • 布林(Booleans):會根據 Boolean 值回
  • 數值(Numbers):除了 0, or NaN 會是 false 外,其他都是 true
  • 字串(String):除了空字串 '' 會是 false 之外,其他都是 true(字串中有空格也是 true)

code style

1
2
// 單行的 if 可以不用加上 {...}
if (lemons) console.log('hello')

16.1 Use braces with all multi-line blocks @ airbnb

  • 不要在 else 中使用 return

16.3 no-else-return @ airbnb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// bad
function foo() {
if (x) {
return x;
} else {
return y;
}
}

// good
function foo() {
if (x) {
return x;
}

return y;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// bad
function cats() {
if (x) {
return x;
} else if (y) {
return y;
}
}


// good
function cats() {
if (x) {
return x;
}

if (y) {
return y;
}
}
  • if 當中的條件式太長的時候,可以換行並把比較運算子放在最前面(17.1 @ airbnb):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// good
if (
foo === 123
&& bar === 'abc'
) {
thing1();
}

// good
if (
(foo === 123 || bar === "abc")
&& doesItLookGoodWhenItBecomesThatLong()
&& isThisReallyHappening()
) {
thing1();
}

// good
if (foo === 123 && bar === 'abc') {
thing1();
}

比較運算子(comparison operator)

  • 使用 ===!==

其餘參數(rest parameter)

其餘運算字會幫助我們把輸入函式中的參數值變成陣列的形式(多個值 => 陣列):

1
2
3
4
5
let avg = function(...arr){
console.log(arr) // [1,3,5,7,9]
}

console.log(avg(1,3,5,7,9))

展開語法(spread syntax)

展開運算子則是可以把陣列中的元素取出(陣列 => 多個值):

複製陣列(Copy an array)

1
2
3
4
5
6
var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
arr2.push(4);

// arr2 becomes [1, 2, 3, 4]
// arr remains unaffected

連結陣列(concatenate arrays)

1
2
3
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2]; // [ 0, 1, 2, 3, 4, 5 ]

將陣列代入函式中

1
2
3
let number = [1,2,3,4,5];
console.log(Math.max(...number)); // 5
console.log(...number); // 1,2,3,4,5

複製物件(Copy Objects)

1
2
3
4
5
6
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

// 使用 Object.assign() 會觸發 setters,而 spread syntax 不會
var clonedObj = { ...obj1 }; // Object { foo: "bar", x: 42 }
var mergedObj = { ...obj1, ...obj2 }; // Object { foo: "baz", x: 42, y: 13 }

邏輯運算子

keywords: short circuit boolean operator
double and &&
1
2
3
4
5
6
//  原則:如果前者為真,則回傳後者;如果前者為假,則回傳前者,後面的都不考慮

console.log(3 === 3 && 'apple' === 'apple') // true(因為 'apple' === 'apple')
console.log(3 === 3 && 'apple') // 'apple',如果自己為真,則回傳後者
console.log(3 === 3 && 'apple' && 'chicken') // 'chicken'
console.log(3 === 3 && false && 'chicken') // 'false',如果自己為假,就會回傳它自己
使用情境
1
2
3
4
5
6
7
8
9
// 使用情境:判斷前面的項目是不是都正確,如果是的話,在執行後者

callback && callback() // 如果 callback 存在,則執行()

/**
* 如果 token.authenticate 存在則 secret = token.number
* 否則 secret = token.authenticate
**/
let secret = token.authenticate && token.number
double or ||
1
2
3
4
//  原則:如果前者為真,則回傳前者,後面都不考慮;如果前者為假,則回傳後者

console.log(3 === 3 || false || 'chicken') // true(因為 3 === 3)
console.log(3 === 4 || false || 'chicken') // 'chicken'
1
2
//  使用時機:設定預設值時
let width = window.innerHeight || 300 // 如果 window.innerHeight 不存在,則 width 為 300

switch case

當需要在 switch 的 case 中定義變數時,casedefault 後面要加上大括號{ }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// bad
switch (foo) {
case 1:
let x = 1;
break;
case 2:
const y = 2;
break;
case 3:
function f() {
// ...
}
break;
default:
class C {}
}

// good
switch (foo) {
case 1: {
let x = 1;
break;
}
case 2: {
const y = 2;
break;
}
case 3: {
function f() {
// ...
}
break;
}
case 4:
bar();
break;
default: {
class C {}
}
}

15.5 Use braces to create blocks in case and default clauses that contain lexical declarations (e.g. let,const, function, and class). @ airbnb

位元 NOT 運算子(波浪號)

任何 >=0 的值都會是非 0 的結果

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 使用情境:用在判斷式
* 如果是 indexOf 回傳的值是 -1 表示找不到,那麼加上 ~ 之後會變 0 ,放在 if 裡面變成 false
**/

// 等同於 if(String.indexOf('e') >= 0){ ... }
if(~String.indexOf('e')){
console.log('Find it')
}

// 用在正數無條件捨去,類似 Math.floor() 但是當裡面的數值為負數時則結果不同
console.log(~~1.45345) // 1

條件三元判斷式(ternary operator)

1
2
// (條件) ? 條件成立 : 條件不成立
const status = age >= 18 ? 'adult' : 'minor';

空值聯合運算子(nullish coalescing operator)

Nullish Coalescing Operator @ MDN

可以視為 || 的強化版。當使用 nullish coalescing operator (??) 時,只有當左側的值是 nullundefined 時,才會採用右側的值,否則會使用左側的值:

1
2
3
4
5
6
7
// 當左側的值是 undefined 或 null 時,則回傳右側的值
undefined ?? 'foo'; // foo
null ?? 'foo'; // foo

// 除了 undefined 或 null 之外,則都會回傳左側的值
false ?? 'foo'; // false
0 ?? 'foo'; // 0

optional chaining operator

可以視為物件取用屬性時 . 的強化版,使用 ?. 當左側的屬性不存在,即使繼續取用內部屬性也不會噴錯,而是得到 undefined

1
2
3
4
5
6
7
8
9
10
11
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah',
},
};

const dogName = adventurer.dog?.name;

dogName; // undefined,若 dog 屬性不存在
adventurer.someNonExistentMethod?.(); // undefined,若 someNonExistentMethod 方法不存在

可以搭配 nullish coalescing operator 使用:

1
2
const dogName = adventurer.dog?.name ?? 'Daniel';
console.log(dogName); // 'Daniel'

delete

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* delete
* 假如 delete 運算子使用成功, 它會將物件或是 property 設定為 undefined。 delete 運算子會在運算成功時回傳 true ,失敗時回傳 false 。
* 一般定義的物件是無法用 delete 刪除(你可以用 delete 運算子來刪除隱式宣告的變數, 但不適用於宣告過的變數。)
* 因此比較適合用來刪除物件屬性
**/
delete objectName; // 宣告過就無法透過 delete 刪除
delete objectName.property; // 可以刪除
delete objectName[index];


/**
* object instanceof constructor
* 看看 object 是否為 constructor 所建構的實例
**/
function Foo(){}
const bar = new Foo
console.log(bar instanceof Foo)

其他

typeof

1
2
3
/**
* typeof 運算元;typeof (運算元)
**/

instanceof

1
2
3
4
5
6
7
/**
* object instanceof constructor
* 看看 object 是否為 constructor 所建構的實例
**/
function Foo(){}
const bar = new Foo
console.log(bar instanceof Foo)

參考

運算式與運算子 @ MDN

掃描二維條碼,分享此文章