JS魔法堂:從void 0 === undefined說起
一、前言
當使用coffeescript書寫如下程式碼時 name = person?.name 會被預編譯為 var name = typeof person !== "undefined" && person !== null ? person.name : void0; ,那麼void 0到底是什麼意思呢?執行得知void 0===undefined為true。那為什麼不直接使用undefined而要使用void 0呢?而一元運算子void具體又有什麼作用呢?下面將展開來說明。
二、為什麼不直接用undefined
undefined在JavaScript中並不屬於保留字/關鍵字,因此在IE5.5~8中我們可以將其當作變數那樣對其賦值(IE9+及其他現代瀏覽器中賦值給undefined將無效)
var undefinedBackup = undefined; undefined = 1; // 顯示"undefined" console.log(typeof undefinedBackup); // 在IE5.5~8中顯示"number",其他瀏覽器中則顯示"undefined" console.log(typeof undefined);
於是採用void方式獲取undefined則成了通用準則。
三、一元運算子void的作用
void在ECMAScript 262規範如下:
The void Operator
The production UnaryExpression : void UnaryExpression is evaluated as follows:
- Let expr be the result of evaluating UnaryExpression.
- Call GetValue(expr).
- Return undefined.
NOTE: GetValue must be called even though its value is not used because it may have observable side-effects.
void的行為特點為:
1. 不管void後的運算數是什麼,只管返回純正的undefined;
2. void會對其後的運算數作取值操作,因此若屬性有個getter函式,那麼就會呼叫getter函式(因此會產生副作用)
var article = { _view: 0, get view(){ console.log(this._view); return this._view++; } }; var test = void article.view; // 顯示0 console.log(test); // 顯示undefined console.log(article._view); // 顯示1
通過一元運算子 delete 作對比,delete的其中一個行為特點是不對其運算數進行取值操作(delete的其他行為特點比我們想的複雜得多,這裡就不詳細記錄了)
var article = { _view: 0, get view(){ console.log(this._view); return this._view++; } }; var ret = delete article.view; console.log(ret); // 顯示true console.log(article._view); // 顯示0
四、還有啥方式可以得到純正的undefined?
除了通過一元運算子void獲取純正的undefined,其實我們還有如下方法來獲取:
1. 未賦值的變數
var myUndefined; console.log(typeof myUndefined); // 顯示"undefined"
2. 未賦值的實參(和未賦值的變數同理)
var getUndefined = function(undefined){ return undefined; }; var myUndefined = getUndefined(); // 或通過arguments獲取 var getUndefined = function(){ return arguments[arguments.length]; };
3. 無返回值函式
var getUndefined = function(){}; var myUndefined = getUndefined();
4. 未定義的屬性
var myUndefined1 = {}['']; var myUndefined2 = [][0];
五、總結
一個小小的void和undefined就這麼好玩,前端的世界還有很多事情要深入研究哦!!