顯示廣告
隱藏 ✕
※ 本文為 terievv 轉寄自 ptt.cc 更新時間: 2018-10-12 08:06:56
看板 Ajax
作者 eight0 (人類)
標題 Re: [問題] 關於setTimeout寫法
時間 Sun Sep 16 00:42:34 2018


setTimeout 接受兩種參數︰

var timeoutID = scope.setTimeout(function[, delay, param1, param2, ...]);
var timeoutID = scope.setTimeout(code[, delay]);

你的正常寫法和錯誤寫法,分別對應第一種、第二種呼叫方法,這裡就不說明。

來看你的錯誤寫法︰

: setTimeout(console.log(2),1000);

console.log(2) 會呼叫 console.log 這個函式,並傳入參數 2。console.log 這個函式
沒有回傳值,得到的結果是 undefined。也就是說,你的錯誤寫法相當於

1. 執行 console.log(2) 之後
2. 使用 undefined 作為第一個參數傳入 setTimeout︰

  setTimeout(undefined,1000);

那為什麼沒有錯誤?

因為當 setTimeout 接受到的第一個參數不是函式的時候,會嘗試將該數值轉成字串。也
就是說,它相當於︰

  setTimeout((undefined).toString(),1000);
  setTimeout('undefined',1000);

你相當於在一秒後執行了一段內容為「undefined」的程式碼。

基於這個特性,我們其至可以把要執行的程式碼設置成 toString 的回傳內容︰

  const foo = {};
  foo.toString = () => "console.log('hello')";
  setTimeout(foo, 1000);
  // 在一秒後印出 hello


參考︰

* MDN 上的 setTimeout 文件︰
  https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
WindowOrWorkerGlobalScope.setTimeout() - Web APIs | MDN
[圖]
The setTimeout() method of the WindowOrWorkerGlobalScope mixin (and successor to window.setTimeout) sets a timer which executes a function or specifie ...

 
  (縮︰https://is.gd/YOpwh2
WindowOrWorkerGlobalScope.setTimeout() - Web APIs | MDN
[圖]
The setTimeout() method of the WindowOrWorkerGlobalScope mixin (and successor to window.setTimeout) sets a timer which executes a function or specifie ...

 

* setTimeout 的詳細實作參考︰
  https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
  (縮︰https://is.gd/4DlMT2

--

額外補充,如果你希望在遇到這種情況時能產生錯誤提醒開發者,可以使用具有 type
check 功能的工具,例入 TypeScript 或 Flow。

以下是在 Flow 的 REPL,可以看到對 setTimeout 傳入 undefined 產生的錯誤︰
https://flow.org/try/#0PQKgBAAgZgNg9g...wxYB08A5pQEwCUANGACMABlE8A3KiA
Try Flow | Flow
[圖]
Interactive Flow REPL ...

 
(縮︰https://is.gd/O5Bjdk
Try Flow | Flow
Interactive Flow REPL ...

 

--
                                      ▏                                      
                                      ▏                                      
                                   ◣                                  
                                  ▄▆                                
                                  ◥    ◤                                
                                   ▄                                         

--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.250.158.95
※ 文章代碼(AID): #1RdJQ36T (Ajax)
※ 文章網址: https://www.ptt.cc/bbs/Ajax/M.1537029763.A.19D.html
Kenqr: 推1F 09/16 13:05
blues520520: 謝謝大大解釋2F 09/16 13:56
ochitsuite: 推3F 09/16 14:18
peanut97: 這個教學太精闢了!!!!4F 09/16 23:59
cutekid: 大推(Y)5F 09/17 11:17
kyrc: 推~6F 09/17 11:49
shvanta: 簡潔明瞭,讚7F 09/28 15:06
akccakcctw: 清楚明瞭8F 09/29 09:48
pk740111: 解釋得太棒了!9F 09/30 01:15
ostkaka: 推 解釋的很清楚10F 10/10 01:35
visa9527: 第二種呼叫方法本身是用 eval 在跑嗎 ?11F 10/11 11:16

--
※ 看板: terievv 文章推薦值: 0 目前人氣: 0 累積人氣: 136 
分享網址: 複製 已複製
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇
看板名稱: 確定(Enter) 取消(Esc) 搜尋(Space)
查詢帳號: 確定(Enter) 取消(Esc) 搜尋(Space)
搜尋: m)m文 b)進板 c)未分類 a)作者 /)標題 q)取消?[q]

搜尋 送出(Enter) 取消(Esc)

回覆文章至: f)看板 m)作者信箱 b)兩者皆是 q)取消?[f]
要引用原文嗎? y)引用原文 n)不引用 a)全部回覆 r)複製原文 q)取消?[y]
轉錄本文章於看板: 1)使用連結 2)使用複製 q)取消 ?[1]
轉寄至站內信箱於使用者: 確定(Enter) 取消(Esc)
轉寄至站內信箱於使用者: 確定(Enter) 取消(Esc)
修改文章標題為: 確定(Enter) 取消(Esc)
修改文章標題為: 確定(Enter) 取消(Esc) 全部(a)

確定要刪除這篇文章?(可按大U救回) 確定(Enter) 取消(Esc)

刪除理由:

確定(Enter) 取消(Esc)
加到這個分類: 確定(Enter) 下一層(→) 回上層(←) 取消(Esc)
你覺得這篇文章: 1)真讚 2)真瞎 q)取消?[1] (再選一次即可收回)
你覺得這篇文章: 1)值得推薦 2)表示反對 3)單純註解 q)取消?[3]
guest
預覽(Enter) 取消(Esc)
上傳圖片
按ctrl+Enter可輸入下一行。
guest
確定要送出? 確定(Enter) 取消(Esc) 繼續(e)
搜尋: 送出(Enter) 取消(Esc)

▏▎▍▌▋▊▉ 請按任意鍵繼續