原文:http://www.2ality.com/2011/05/void-operator.html
語法
void expr
void運算符的作用是:計算表達式expr,並返回undefined.例子:
> void 0 undefined > void(0)
undefined
> void 4+7 // 由於void比+優先級更高,所以該表達式被解析為(void 4)+7 NaN
> void(4+7)
undefined
> var x;
> x = 3;
3
> void(x = 5);
undefined
> x
5
void是個運算符,而不是函數,它不能被重新定義,如果自定義一個void函數,會拋出異常,像下面這樣:
>function void(expr) { // 這里會報錯 return undefined;
}
SyntaxError: Unexpected token void
譯者注:在Firefox中,上面的代碼只有在嚴格模式下才會報錯,其他的關鍵字和保留關鍵字作為函數聲明的函數名時也一樣.
>function void(expr) { // 沒有報錯,但不會真正聲明一個void函數 return undefined;
}
>function void(expr) { // 嚴格模式下會報錯
"use strict";
return undefined;
}
SyntaxError: redefining void is deprecated
>function class(expr) { // class也是個保留關鍵字
"use strict";
return undefined;
}
SyntaxError: redefining class is deprecated
void的三種用途.
本文剩余的部分講講void運算符的三種用途:
- 用void 0代替undefined
- 書簽小程序
- 在鏈接中執行JavaScript代碼
用途1: 用void 0代替undefined
void 0或者void(0)總是等於undefined,只有一個例外:undefined被重新賦值的時候:
> function a(undefined) { return undefined; } //這里的undefined是個局部變量 > a("hello") ’hello’ > undefined = "foo"; //這個undefined實際上是window.undefined > console.log(undefined); foo
而void不用擔心被重新賦值:
> function b() { var void = function() {}; return void(0); }
missing variable name
function b() { var void = function() {}; return void(0); }
.......................^
> void = "foo";
syntax error
void = "foo";
......^
譯者注:通常使用的undefined實際上就是window.undefined(屬性名和值的名稱相同,window.NaN,window.Infinity也類似),它是一個全局變量,在ES3的引擎上,這個變量可以被修改.而在ES5的引擎上,它是window的只讀屬性,不能被重新賦值,只是在非嚴格模式下,該賦值操作會靜默失敗,而在嚴格模式下,會拋出異常.
Firefox3.6下(只實現了部分ES5特性,在這里算是ES3引擎)
>undefined = true; >console.log(undefined); trueFirefox18下(完全實現了ES5)
>(function () { undefined = true; // 沒有報錯,但其實沒有賦值成功 console.log(undefined); })() undefined >(function () { "use strict"; undefined = true; // 嚴格模式,為只讀屬性賦值會拋出異常 })() TypeError: "undefined" is read-only
如果你無論如何都擔心全局的undefined變量會被別人修改,那就使用void 0.否則,使用讓人更容易明白的undefined,因為並不是所有閱讀你的代碼的人都熟悉void運算符.
譯者注:現在很流行的做法是把自己的代碼都寫在一個自執行的函數表達式里,函數內部使用一個局部的undefined變量,這樣可以保證undefined變量的值是真實的undefined.
//ES3引擎下 >undefined = true; >console.log(undefined) true >(function (undefined) { console.log(undefined) //undefined是個參數,但沒有傳入對應的實參,因此它的值就是真實的undefined })() undefined
用途2: 書簽小程序
書簽小程序(Bookmarklets)是一個能夠執行JavaScript代碼的URI(譯者注:使用JavaScript偽協議).如果一個bookmarklet返回的結果不是undefined,那么當前頁面顯示的內容會被這個返回值替代.這時候就得用到void運算符.[Webkit內核的瀏覽器不會有這樣的麻煩]:
- javascript:3+4 會把當前頁面的內容替換成7.
- javascript:void(3+4) 不會改變當前頁面的內容.void會“隱藏”掉表達式3+4的結果.
類似的:
- javascript:window.open("http://www.whitehouse.gov/") 會替換掉當前頁面的內容.
- javascript:void window.open("http://www.whitehouse.gov/") 不會改變當前頁面的內容.
更復雜的例子:這個bookmarklet可以把當前頁面的URL提交到submit.example.com:
javascript:void window.open("http://submit.example.com/submit?"+encodeURIComponent(document.location.href))
這個bookmarklet不會改變當前頁面的內容,會在新標簽或新窗口中打開頁面.
譯者注:網上有很多流行的Bookmarklet,通常是導入了另外一個js文件,比如繁體字轉換成簡體字,比如購物網站比價.
javascript: void(document.body.appendChild(document.createElement("script")).src = "http://tongwen.openfoundry.org/NewTongWen/tools/bookmarklet_cn2.js")
用途3: 在鏈接中執行JavaScript代碼
雖然這種做法是不推薦的,但的確是可行的,例如下面的代碼:
<a href="javascript:void computeResult()">Compute</a>
如果函數computeResult()返回undefined(或者沒有return語句,也默認返回undefined),則不會有什么事.但如果這個函數返回了其他的值,那么你必須在函數前面添加void運算符來防止它改變當前頁面的內容.[Webkit內核的瀏覽器不會有這樣的麻煩].
譯者注:更常見的用法是:javascript:void(0),用來阻止鏈接默認的跳轉行為.