談?wù)凧avascript中的void操作符 ---- void xx

在讀源碼的時候,看到作者有寫 void 0眶拉,不是很懂,看來別人的一篇文章感覺又學(xué)到一些東西憔儿,就把這篇文章搬了過來忆植。


由于JS表達(dá)式偏啰嗦,于是最近便開始采用Coffeescript來減輕負(fù)擔(dān)谒臼。舉個栗子朝刊,當(dāng)我想取屋子里的第一條dog時,首先要判斷house對象是否存在蜈缤,然后再判斷house.dogs是否存在拾氓,最后取house.dogs[0]。在JS需要這么寫

var dog = (typeof house !== 'undefined && house !== null) && house.dogs && house.dogs[0]

在Coffee中底哥,我只需要這么寫:

dog = house?.dogs?[0];

寫到這里咙鞍,讀者會問房官,這跟標(biāo)題《Javascript中的void》有一毛錢關(guān)系?Coffee的本質(zhì)就是JS续滋,之所以Coffee能工作的很好翰守,是因為它生成出了高效而且健壯的JS代碼,我們可以看看它的生成結(jié)果疲酌。

var dog, _ref;

dog = typeof house !== "undefined" && house !== null ? (_ref = house.dogs) != null ? _ref[0] : void 0 : void 0;

短短一行Coffee代碼生成出了如此長的JS代碼蜡峰,看上去似乎比我最前面自己用JS寫的更靠譜更安全,末尾還出來了兩個void 0朗恳,這究竟是何方神圣湿颅?

結(jié)構(gòu)化一下上面的例子:

dog = (typeof house !== "undefined" && house !== null) ? 
        ((_ref = house.dogs) != null ? _ref[0] : void 0 ) 
        : void 0;

如果

house

未定義或

house

null

時,返回

void 0

如果

house.dogs

null

時粥诫,返回

void 0

void 0究竟是什么值油航,這個倒很容易測試:

typeof void 0 //得到"undefined"
console.log(void 0) //輸出undefined

似乎void 0就是undefined了,但這樣子路數(shù)太野臀脏,也不夠嚴(yán)謹(jǐn)劝堪,即無法回答:void 100,?void hello(),?void i++這無數(shù)可能組合的值是什么?

我們來瞅瞅規(guī)范是怎么說的吧揉稚。

規(guī)范是這么說的

ECMAScript 262規(guī)范秒啦,有如下描述:

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操作符

產(chǎn)生式?UnaryExpression?: void?UnaryExpression?按如下流程解釋:

  • 令?expr?為解釋執(zhí)行UnaryExpression的結(jié)果。
  • 調(diào)用?GetValue(expr).
  • 返回 undefined.

注意:GetValue一定要調(diào)用搀玖,即使它的值不會被用到余境,但是這個表達(dá)式可能會有副作用(side-effects)。

重點在于:無論void后的表達(dá)式是什么灌诅,void操作符都會返回undefined. 因此上面由Coffee編譯出來的代碼我們可以認(rèn)為是這樣的:

dog = (typeof house !== "undefined" && house !== null) ? 
        ((_ref = house.dogs) != null ? _ref[0] : undefined ) 
        : undefined ;

問題來了芳来,既然(void 0) === undefined,那直接寫undefined不就行了么猜拾?

為什么要用void即舌?

因為undefined在javascript中不是保留字。換言之挎袜,你可以寫出:

function joke() {
    var undefined = "hello world";
    console.log(undefined); //會輸出"hello world"
}
console.log(undefined); //輸出undefined

對的顽聂,你可以在一個函數(shù)上下文內(nèi)以undefined做為變量名,于是在這個上下文寫的代碼便只能通過從全局作用域來取到undefined,如:

window.undefined //瀏覽器環(huán)境
GLOBAL.undefined //Node環(huán)境

但要注意的是,即便window, GLOBAL仍然可以在函數(shù)上下文被定義耐版,故從window/GLOBAL上取undefined并不是100%可靠的做法。如:

function x() {
   var undefined = 'hello world',
       f = {},
       window = {
           'undefined': 'joke'
       };
   console.log(undefined);// hello world
   console.log(window.undefined); //joke
   console.log(f.a === undefined); //false
   console.log(f.a === void 0); //true
}

于是耀石,采用void方式獲取undefined便成了通用準(zhǔn)則。如underscore.js里的isUndefined便是這么寫的:

_.isUndefined = function(obj) {
    return obj === void 0;
}

除了采用void能保證取到undefined值以外爸黄,還有其它方法嗎滞伟?有的揭鳞,還有一種方式是通過函數(shù)調(diào)用。如AngularJS的源碼里就用這樣的方式:

(function(window, document, undefined) {
    //.....
})(window, document);

通過不傳參數(shù)诗良,確保了undefined參數(shù)的值是一個undefined汹桦。

其它作用

除了取undefined外,void還有什么其它用處嗎鉴裹?

還有一個常見的功能舞骆,填充href。下面是一個微博截圖径荔,它的轉(zhuǎn)發(fā),?收藏督禽,?討論都是超鏈接,但是用戶并不希望點擊它們會跳轉(zhuǎn)到另一個頁面总处,而是引發(fā)出一些交互操作狈惫。

理論上而言,這三個超鏈接都是沒有URL的鹦马,但如果不寫的話胧谈,呵呵,點擊它會刷新整個頁面荸频。于是便用上了href="javascript:void(0)的方式菱肖,確保點擊它會執(zhí)行一個純粹無聊的void(0)

另一種情況是旭从,如果我們要生成一個空的srcimage稳强,最好的方式似乎也是src='javascript:void(0)',參見StackOverflow上的這個問題:What's the valid way to include an image with no src?

寫在最后

回到void的定義和悦,有一句話特別讓人迷惑:

注意:GetValue一定要調(diào)用退疫,即使它的值不會被用到,但是這個表達(dá)式可能會有副作用(side-effects)鸽素。

這是什么意思褒繁?這表示無論void右邊的表達(dá)式是什么,都要對其求值馍忽。這么說可能不太明白棒坏,在知乎上winter大神有過闡述關(guān)于js中void,既然返回永遠(yuǎn)是undefined舵匾,那么GetValue有啥用?谁不,我且拾人牙慧坐梯,代入一個場景,看代碼:

var happiness = 10;
var girl = {
    get whenMarry() {
        happiness--;
        return 1/0; //Infinity
    },
    get happiness() {
        return happiness;
    }
};

console.log(girl.whenMarry); //調(diào)用了whenMarry的get方法
console.log(girl.happiness); // 9

void girl.whenMarry; //調(diào)用了whenMarry的get方法
console.log(girl.happiness); // 8

delete girl.whenMarry; //沒有調(diào)用whenMarry的get方法
console.log(girl.happiness); //還是8

上述代碼定義了一個大齡文藝女青年刹帕,每被問到什么時候結(jié)婚呀(whenMarry)吵血,happiness都會減1谎替。從執(zhí)行情況可以看出,無論是普通訪問girl.whenMarry蹋辅,還是void girl.whenMarry都會使她的happiness--钱贯。而如果把void換成delete操作符寫成delete girl.whenMarry,她的happiness就不會減了侦另,因為delete操作符不會對girl.whenMarry求值秩命。

總結(jié)

void有如下作用:

通過采用

void 0

undefined

比采用字面上的

undefined

更靠譜更安全,應(yīng)該優(yōu)先采用

void 0

這種方式褒傅。

填充<a>href確保點擊時不會產(chǎn)生頁面跳轉(zhuǎn); 填充<image>src弃锐,確保不會向服務(wù)器發(fā)出垃圾請求。

- 完 -


原文鏈接:https://segmentfault.com/a/1190000000474941

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末殿托,一起剝皮案震驚了整個濱河市霹菊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌支竹,老刑警劉巖旋廷,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異礼搁,居然都是意外死亡饶碘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門叹坦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熊镣,“玉大人,你說我怎么就攤上這事募书⌒鞔眩” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵莹捡,是天一觀的道長鬼吵。 經(jīng)常有香客問我,道長篮赢,這世上最難降的妖魔是什么齿椅? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮启泣,結(jié)果婚禮上涣脚,老公的妹妹穿的比我還像新娘。我一直安慰自己寥茫,他們只是感情好遣蚀,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般芭梯。 火紅的嫁衣襯著肌膚如雪险耀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天玖喘,我揣著相機(jī)與錄音甩牺,去河邊找鬼。 笑死累奈,一個胖子當(dāng)著我的面吹牛贬派,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播费尽,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼赠群,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了旱幼?” 一聲冷哼從身側(cè)響起查描,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柏卤,沒想到半個月后冬三,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡缘缚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年勾笆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桥滨。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡窝爪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出齐媒,到底是詐尸還是另有隱情蒲每,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布喻括,位于F島的核電站邀杏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏唬血。R本人自食惡果不足惜望蜡,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拷恨。 院中可真熱鬧脖律,春花似錦、人聲如沸腕侄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至膏孟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拌汇,已是汗流浹背柒桑。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留噪舀,地道東北人魁淳。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像与倡,于是被迫代替她去往敵國和親界逛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容