前兩天在開發項目的公共基礎庫時,無心間在看 moment.js 源代碼的時候發現這樣一個 util 函數。這個函數做用無非就是判斷輸入否是 undefined ,這個不是關鍵,關鍵是 void 這個引發了個人注意,這裏爲何不直接使用 input === undefined ?而是使用這種形式來判斷了。帶着疑問咱們今天就一塊兒來看看 JavaScript void 運算符。javascript
export default function isUndefined(input) {
return input === void 0;
}
複製代碼
void 運算符 對給定的表達式進行求值,而後返回 undefined。語法就是 void expression 。void 是一個一元運算符,它能夠出如今任意類型的操做數以前執行操做數,卻忽略操做數的返回值,返回一個 undefined。void 在表達式的左邊,void 右邊的表達式能夠是帶括號形式(例如:void(0)),也能夠是不帶括號的形式(例如:void 0)。java
若是有印象的同窗是否是會發現,咱們在阻止 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
在使用當即執行的函數表達式時,能夠利用 void 運算符讓 JavaScript 引擎把一個function關鍵字識別成函數表達式而不是函數聲明(語句)。express
void function iife() {
var bar = function () {};
var baz = function () {};
var foo = function () {
bar();
baz();
};
var biz = function () {};
foo();
biz();
}();
複製代碼
箭頭函數標準中,容許在函數體不使用括號來直接返回值。 若是右側調用了一個本來沒有返回值的函數,其返回值改變後,則會致使非預期的反作用。 安全起見,當函數返回值是一個不會被使用到的時候,應該使用 void 運算符,來確保返回 undefined(以下方示例),這樣,當 API 改變時,並不會影響箭頭函數的行爲。segmentfault
button.onclick = () => void doSomething();
複製代碼
確保了當 doSomething 的返回值從 undefined 變爲 true 的時候,不會改變函數的行爲。安全
因爲 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
複製代碼
在 262 ECMA 中,對 void 有一個執行步驟的解釋,大體的解讀一下:框架
注意最後的一句話,GetValue必定要調用,即便它的值不會被用到,可是這個表達式可能有反作用。其實這個反作用是什麼,並無解釋。既然void xx === undefined,咱們回到最開始的問題,哪 void 0 、void 100、void xx()、void 無論什麼操做,返回的都是 undefined 。哪爲何在 moment.js 中不直接寫 input === undefined。函數
咱們知道 undefined 在 JavaScript 中是一個保留字。哪既然他是一個保留字,咱們就能夠爲它賦值。
function test() {
var undefined = "不愛吃貓的魚er";
console.log(undefined); // 不愛吃貓的魚er
}
test();
console.log(undefined); // undefined
複製代碼
賦值以後你提取到的 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/…