ECMAScript 如同 C 語言也有 void
,但存在感很低,甚至很多人從來沒使用過。
Version
macOS Catalina 10.15.2
VS Code 1.41.1
Quokka 1.0.274
ECMAScript 2015
Definition
void << expression >>
無論搭配任何 expression,皆回傳 undefined
若以白話來說, void
相當於以下實作:
let void = function(expression) {
return undefined
}
Why ?
根據 JavaScript 爸爸 Brendan Eich 所言:
I added the
void
operator to JavaScript before Netscape 2 shipped to make it easy to discard any non-undefined value in a JavaScript URL.
<a href="javascript:void window.open('https://www.google.com')">Google</a>
window.open()
會開啟新的 tab,並回傳 window
object,這會導致一些 browser 將目前頁面也導向新的連結,使用 void
會捨棄 window
object 而回傳 undefined,這使得 browser 不會改變原來頁面,這是 Brendan Eich 設計 void
初衷。
void 0
if (x === void 0) // always safe
在 ES3,undefined 為 global object,因此能夠被修改,而 void 0
永遠是 undefined,不會被修改,所以可使用 void 0
取代 undefined。
undefined 在 ECMAScript 5 之後被定義為 read-only,不能被修改,因此使用
void 0
取代 undefined 的動機已經不再如以往那麼強烈
Make Expression to Undefined
<a href="javascript:void(0)" @click="onClick">Google</a>
以 Vue 而言,void
大概只有在這裡會看到,為了要讓 <a/>
有底線,所以一定得加上 href
,但實際卻是執行 @click
的 onClick()
,此時我們必須加上 javascript:void(0)
使 href
成為 undefined,喪失原本 hyperlink 該有的功能。
IIFE
let inc = x => x + 1;
(function() {
let result = inc(2)
console.log(result)
})();
IIFE 的標準寫法,是將 function() {}
以括號刮起來,再加上 ()
立即執行。
let inc = x => x + 1;
void function() {
let result = inc(2)
console.log(result)
}();
若你覺得加上 ()
很醜不易閱讀,也可以在 function() {}
前加上 void
,這會強迫 void
之後的 function 加以運算,然後透過 ()
立即執行。
let inc = x => x + 1;
(() => {
let result = inc(2)
console.log(result)
})();
IIFE 也可搭配 arrow function,但只能使用 ()
而不能使用 void
,因為 =>
會造成誤判,只能使用 ()
。
let inc = x => x + 1
void (() => {
let result = inc(2)
console.log(result)
})()
若 arrow function 搭配 IIFE,且又要使用 ASI,則 ()
與 void
都要用上,因為一開始的 ()
不適用於 ASI,要透過 void
強迫執行。
Non-value-return Arrow Function
import { map, filter, reduce, pipe, tap } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let log = x => console.log(x)
let fn = val => pipe(
filter(x => x.title.includes(val)),
map(x => x.price),
tap(log),
reduce((a, x) => a + x, 0),
)
fn('JavaScript')(data)
組合 function 時,我們會希望傳入 higher order function 為 pure function,也就是都有回傳值,但有時候還是得使用 side effect,如 console.log()
就是典型 side effect。
第 9 行
let log = x => console.log(x)
這樣寫雖然可行,但語意上可能認為其為 pure function。
let log = x => void console.log(x)
比較好的寫法是加上 void
,可明確表示其為 side effect。
Conclusion
- 以
void 0
取代 undefined 具有時代意義,目前已經不太需要 href="javascript:void(0)"
是今日還可以看到void
的少數場景- 將
void
用於 IIFE 也是不錯的點子,可避免()
不易閱讀 - Arrow function 也可用於 IIFE,但只能使用
()
,若也使用 ASI,則()
與void
都要用上 - 若 pure function 要搭配 higher order function,可在 pure function 明確加上
void
表示有 side effect
Reference
Dr. Axel Rauschmayer, Speaking JavaScript
Slikts, A case for using void in modern JavaScript