(void 0) 與 undefined 之間的小九九

謙龍發表於2017-05-09

前言

原文連結

原始碼地址

這是underscore.js原始碼分析的第一篇文章,為什麼選擇寫這篇文章呢?其實主要有兩點

  1. 下劃線原始碼中通篇可見這樣的判斷obj === void 0,初次看這樣的寫法完全不知道什麼意思,所以想整明白它。
  2. 決定寫一個系列把下劃線分析完整,希望由淺入深,柿子撿軟的捏,先從簡單的開始入手(?)

寫完這篇文章希望達到什麼樣的效果呢?

  1. 說明白為什麼用(void 0)代替undefined

  2. (void 0)的一些簡單應用

(void 0) 與 undefined 之間的小九九
https://user-gold-cdn.xitu.io/2017/5/9/ee6837151ae5b8737445980b3841cdce

void 0是個啥

void 0是個啥,為毛它可以直接代替undefined關鍵字來做判斷呢?我們可以看下mdn上的解釋

The void operator evaluates the given expression and then returns undefined.

void 運算子 對給定的表示式進行求值,然後返回 undefined

啥?去執行了一段表示式,最後卻得到undefined,那要是表示式執行的結果是2、3、8、毛主席萬歲,也是返回undefined嗎?答案是:對的。他就是這麼個東西,不管你表示式裡寫的是個啥,我最後就是給你個undefined。

(void 0) 與 undefined 之間的小九九
黑人問號

undefined又是啥

undefined是js原始型別值之一,也是全域性物件window的屬性,在部分低階別的瀏覽器中可以被修改,在區域性作用域中也可以被修改。

首先我們來看這一段斷碼


var undefined = 'qianlongo'
alert(undefined)複製程式碼

最後console出來的是啥呢?undefined : qianlongo,
沒圖你說個js,接下來擷取部分瀏覽器執行後的截圖

ie7

(void 0) 與 undefined 之間的小九九
ie7

ie8

(void 0) 與 undefined 之間的小九九
ie8

ie9

測試結果為undefined

ie10

(void 0) 與 undefined 之間的小九九
ie10

chrome

在最新的版本58.0.3029.81測試結果為undefined

firefox

在最新的版本52.0.2測試結果為undefined

歐朋瀏覽器

在最新的版本39.0.2256.48測試結果為undefined

你看ie老版本中就是那麼任性,在全域性作用域中可以直接改寫undefined,也就是說當你想知道一個變數是不是等於undefined的時候直接這樣判斷已經不安全了。


if (obj === undefined) {
  // xxx
}複製程式碼

接下來我們再看一段js


var testUndefined = function () {
  var obj = {}
  var undefined = 'underscore'
  var window = {
    'undefined': 'qianlongo'
  }
  console.log(window) // {'undefined': 'qianlongo'}
  console.log(undefined) // underscore
  console.log(window.undefined) // qianlongo
  console.log(obj.name === undefined) // false
  console.log(obj.name === window.undefined) // false
  console.log(obj.name === (void 0)) // true
}

testUndefined()複製程式碼

可以得出,window,undefined本身在區域性作用域中是可以被重寫掉的,同樣的道理,如果你在區域性作用域中同樣用以下程式碼來判斷obj是不是undefined,是有風險的。

if (obj === undefined) {
  // xxx
}複製程式碼

為啥要用void 0來代替undefined

為啥要用void 0來代替undefined,基於以上介紹,原因就在這裡了,void 0無論何時何地,後面跟了什麼,結果都得到undefined,這正好是我們需要的。所以將上面的判斷改寫一下

當然了還要另一個原因void 0 比undefined短

if (obj === void 0) {
  // xxx
}複製程式碼

void 0的一些其他應用

  1. 填充a標籤的href
<div style="height: 10000px;"></div>
<a href="#">xxxx</a>
<script>
  console.log('xxxx')
</script>複製程式碼

上面這段程式碼使用一個#號來填充a標籤的href屬性,這其實是有一些弊端的,比如使用者點選的時候,頁面會回到頂部(網上有人說會重新整理頁面,但是自己試了好像不會),試想我好不容易滾啊滾啊滾到xxxx這幾個文字的地方,一不留神手賤點了一下,瞬間頁面又回到頂部了,是不是要哭死?。

所以常見的解決方法是

<div style="height: 10000px;"></div>
<a href="javascript:void(0)">xxxx</a>
<script>
  console.log('xxxx')
</script>複製程式碼
  1. What's the valid way to include an image with no src?,在這個問題中提到用void 0去替代image標籤的空src屬性會減少頁面請求(是否屬實有待考證)

結尾

第一篇暫時寫完了,歡迎大家吐槽和提意見。

參考文章連結:

What does “javascript:void(0)” mean?

difference between “void 0 ” and “undefined”

void operator

相關文章