JavaScript void 運算符

目錄

  1. void 是什麼?
  2. void 的做用
  3. void 優先級
  4. void 的執行
  5. 爲何要用 void ?

前言

前兩天在開發項目的公共基礎庫時,無心間在看 moment.js 源代碼的時候發現這樣一個 util 函數。這個函數做用無非就是判斷輸入否是 undefined ,這個不是關鍵,關鍵是 void 這個引發了個人注意,這裏爲何不直接使用 input === undefined ?而是使用這種形式來判斷了。帶着疑問咱們今天就一塊兒來看看 JavaScript void 運算符。javascript

export default function isUndefined(input) {
    return input === void 0;
}
複製代碼

1. void 是什麼?

void 運算符 對給定的表達式進行求值,而後返回 undefined。語法就是 void expression 。void 是一個一元運算符,它能夠出如今任意類型的操做數以前執行操做數,卻忽略操做數的返回值,返回一個 undefined。void 在表達式的左邊,void 右邊的表達式能夠是帶括號形式(例如:void(0)),也能夠是不帶括號的形式(例如:void 0)。java

2. void 的做用

1. JavaScript URIs

若是有印象的同窗是否是會發現,咱們在阻止 a 標籤的默認事件是會用到這個。web

<a href="javascript:void(0);">
<a href="javascript:void(0);"> 這個連接點擊以後不會作任何事情,若是去掉 void(), 點擊以後整個頁面會被替換成一個字符 0。 </a>
<p> chrome中即便<a href="javascript:0;">也沒變化,firefox中會變成一個字符串0 </p> <a href="javascript:void(document.body.style.backgroundColor='green');"> 點擊這個連接會讓頁面背景變成綠色。 </a> 複製代碼

注意,雖然這麼作是可行的,但利用 javascript: 僞協議來執行 JavaScript 代碼是不推薦的,推薦的作法是爲連接元素綁定事件。chrome

2. 當即調用的函數表達式

在使用當即執行的函數表達式時,能夠利用 void 運算符讓 JavaScript 引擎把一個function關鍵字識別成函數表達式而不是函數聲明(語句)。express

void function iife() {
    var bar = function () {};
    var baz = function () {};
    var foo = function () {
        bar();
        baz();
     };
    var biz = function () {};
    foo();
    biz();
}();
複製代碼

3. 在箭頭函數中避免泄漏

箭頭函數標準中,容許在函數體不使用括號來直接返回值。 若是右側調用了一個本來沒有返回值的函數,其返回值改變後,則會致使非預期的反作用。 安全起見,當函數返回值是一個不會被使用到的時候,應該使用 void 運算符,來確保返回 undefined(以下方示例),這樣,當 API 改變時,並不會影響箭頭函數的行爲。segmentfault

button.onclick = () => void doSomething();
複製代碼

確保了當 doSomething 的返回值從 undefined 變爲 true 的時候,不會改變函數的行爲。安全

3. void 優先級

因爲 void 運算符的優先級比較高(14),高於普通運算符的優先級,因此在使用時應該使用小括號明確 void 運算符操做的操做數,避免引起錯誤。 在下面的示例代碼中,因爲第一行沒有使用小括號,void 運算符優先計算,恆等於( void 2)- 1,也就是 undefined - 1,結果爲 NaN,在第二行代碼中用括號包含了 (2-1),因此優先因而先計算2-1,在處理 void,恆等於 void (1),結果也就是 undefined。markdown

console.log(void 2 - 1);  //返回NaN
console.log(void (2 - 1));  //返回undefined
複製代碼

4. void 的執行

image.png 在 262 ECMA 中,對 void 有一個執行步驟的解釋,大體的解讀一下:框架

  1. 執行 UnaryExpression 並把返回值賦值給 expr
  2. 調用 GetValue(expr)
  3. 返回 undefined

注意最後的一句話,GetValue必定要調用,即便它的值不會被用到,可是這個表達式可能有反作用。其實這個反作用是什麼,並無解釋。既然void xx === undefined,咱們回到最開始的問題,哪 void 0 、void 100、void xx()、void 無論什麼操做,返回的都是 undefined 。哪爲何在 moment.js 中不直接寫 input === undefined。函數

5. 爲何要用 void ?

咱們知道 undefined 在 JavaScript 中是一個保留字。哪既然他是一個保留字,咱們就能夠爲它賦值。

function test() {
    var undefined = "不愛吃貓的魚er";
    console.log(undefined); // 不愛吃貓的魚er
}
test();
console.log(undefined); // undefined
複製代碼

image.png 賦值以後你提取到的 undefined 就不等於 undefined了,固然若是咱們使用的是 window 對象上的 undefined,也可能被賦值 。因此你直接使用的 undefined ,不必定是100%可靠。因而在不少框架或者基礎 JS 庫中,採用void方式獲取 undefined 便成了通用準則。例如 moment.js、Backbone.js、underscore.js,在他們的源碼中對 undefined 的使用都是使用 void 0 代替。 • moment.js

export default function isUndefined(input) {
    return input === void 0;
}
複製代碼

• Backbone.js

if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;
複製代碼

• underscore.js

_.isUndefined = function(obj) {
    return obj === void 0;
}
複製代碼

除了採用void能保證取到 undefined 值之外,AngularJS 的源碼裏經過函數調用不傳參數,確保了 undefined 參數的值是一個 undefined。

(function(window, document, undefined) {
    //.....
})(window, document);
複製代碼

總結

經過 void xx 這種方式來獲取 undefined,比直接使用 undefined 來的更加可靠安全,因此在不少的庫、框架中都使用 void xx 這種方式來處理undefined ,保證使用到的是安全可靠的 undefined。這種方式咱們在平常的項目開發或者的封裝也能夠借鑑起來。

結束語

若是文章中什麼不對或者寫的很差的地方,請你們多多指正,謝謝!碼字不易,點個贊加個關注吧!

參考

developer.mozilla.org/zh-CN/docs/…262.ecma-international.org/5.1/#sec-11…segmentfault.com/a/119000000…blog.csdn.net/mm19931027/…

相關文章
相關標籤/搜索