iT邦幫忙

1

Javascript 進階 3-6 優先性及相依性

https://ithelp.ithome.com.tw/upload/images/20191216/20121770JKsfyBX2zH.jpg

今天要講的是 優先性相依性

優先性

首先所謂 優先性 ,就是只說我們運算子在運行的時候,會先進行哪種運算。而圖片上面提到的 優先性較高的運算子會成為優先性較低的運算子的運算元 這個概念指的是,運算子是一種表達式,只要是表達式,就會有一個 回傳的值 。而這個回傳的值,會再成為 優先姓較低的運算子運算元 (好饒口~)

接下來我們就來看個實例

var a = 2 * 2 + 2 * 3;
console.log(a);

看到這樣的運算,有學過數學的人就知道,先加減後乘除,所以照這個觀念,我們可以算出 a = 10 的結果。

沒錯,答案是 10 ,而這裡先加減後乘除的觀念就是 運算子的優先性

我們可以從這個 MDN的連結查看各種運算子的優先性

點開以後直接看到表格的部分

https://ithelp.ithome.com.tw/upload/images/20191216/20121770xSdkg2idAD.jpg

乘法跟除法的優先性都是15,大於加法跟減法的13,所以會優先執行乘除之後再執行加減,而別忘了, = 也是運算子的一種喔,只是因為他的優先性很低 只有 3 爾以,所以最後通常算完的結果才會執行這個運算子。

https://ithelp.ithome.com.tw/upload/images/20191216/20121770GKVdLpc0YP.jpg

相依性

再來介紹相依性,相依性就是運算子執行的方向,通常分為 從左至右 以及 從右至左,少部分是 無相依性

這邊 加減乘除 4 個都是屬於 從左至右 ,而賦值的 = 則是屬於 從右至左

好~有了上面這些觀念以後,我們就可以知道, a 透過 運算子優先序 以及 運算子相依性,他的運算邏輯如下

// 先乘除 相依性左到右
2 * 2 = 4
2 * 3 = 6

// 加減 相依性左到右
4 + 6 = 10

// 賦值 相依性右到左
a = 10

那再來提一些特別的案例

console.log(1 < 2 < 3); // true

這個好像還蠻符合預期的。

但當反過來的時候

console.log(3 > 2 > 1); // false

為什麼會這樣呢????

讓我們來解析一下

// 小於大於的符號,優先度一樣是11,那再來就是先相依性的順序都為 從左至右,但這裡必須拆開來看
3 > 2 // 回傳 true, true 在javascript 中會自己型別轉換為 1, 相反 false 就是轉換成 0。
// 所以就變成
1 > 1 // 這邊當然是回傳 false

喔~所以我們的多運算子判斷式,還是會依照相依性的方向,兩個運算元一個運算子一組的進行運算,因為這樣的運算結果的回傳值成為接下來運算子的運算元,應證了一開始圖片上所講的觀念喔!

有興趣的人也可以照著上面的觀念,自己推導看看 console.log(1 < 2 < 3); 為什麼會是 true。

那再來看另一個例子

var a = 1;
var b = 2;
a = b = 3;
console.log(a, b); // 3 , 3

這個結果其實也蠻符合預期的吧~

雖然a, b分別在一開始的時候賦予了不同的值,但最後都被指派成3

順序依照目前的理解是

// 因為 = 是由右邊到左邊的相依性,所以會是這樣
b = 3;
a = b;

所以自然而然,a跟b就是3了阿~

但是,雖然結果是對的,觀念理解卻是錯的喔!!!!!

怎麼說呢? 我們先在來看一個例子喔!

var b = {};
Object.defineProperty(b, 'a', {
    value: 2,
    writable: false
});

上述這個code是指說,我現在宣告一個物件叫b,我要在這個物件b裡面,新增一個屬性,他的keyname是a,並且a的值指派是數字2,更重要的是這個值是不能被複寫的

所以沒有辦法透過 b.a = 3; 來複寫這個值。

var b = {};
Object.defineProperty(b, 'a', {
    value: 2,
    writable: false
});

b.a = 3; // 2
console.log('b.a', b.a);

var a = 3;
a = b.a = 1;

所以這段程式碼執行的結果應該b.a = 2,因為他不會被複寫。

但是下方的 a = b.a = 1; 大家覺得 a 的結果會是多少?

這裡直接公布答案喔,答案是1 ,為甚麼呢,因為同樣,優先性一樣高,依照相依性,由右到左來分析

b.a = 1;

// 這裡雖然b.a的值還是2,但這個表達式會 回傳的值 其實是1喔
// 而重點是回傳的值會再次成為其他運算子的運算元,所以接下來的表達式是等同於

a = 1(b.a = 1的回傳值)

// 所以 a 才等於 1喔!!

就是這個精神,所以如果今天在更複雜改成

var b = {};
Object.defineProperty(b, 'a', {
    value: 2,
    writable: false
});

Object.defineProperty(b, 'b', {
    value: 3,
    writable: false
});

b.a = 3; // 2
console.log('b.a', b.a);

var a = 3;
a = b.b =b.a = 1;

這樣最後a的值呢?還是會是 1喔!

但是b.a也還是2 b.b也還是3喔!

最後再回到

var a = 1;
var b = 2;
a = b = 3;
console.log(a, b); // 3 , 3

所以這邊的順序應該是因為

b = 3; // 回傳 3
a = 3(b = 3的回傳值);

所以這樣a跟b才都是等於3,並非是因為a取得了b的值,所以才等於3。

這篇可能理解上要稍微想過一下,可以想清楚以後在進入下一篇文章喔~汪汪


1 則留言

0
listennn08
iT邦高手 7 級 ‧ 2019-12-17 08:40:59
console.log(1 > 2 > 3);

這段應該是要寫

console.log(3 > 2 > 1);
odinhusky iT邦新手 5 級 ‧ 2019-12-17 08:55:50 檢舉

感謝大大糾正!

我要留言

立即登入留言