JavaScript 系列--JavaScript一些奇淫技巧的實現方法(一)簡短的sleep函數,獲取時間戳

1、前言javascript

有些東西很好用,可是你未必知道;有些東西你可能用過,可是你未必知道原理。
實現一個目的有多種途徑,俗話說,條條大路通羅馬。發散一下你們的思惟以及拓展一下知識面。前端

 

2、實現一個簡短的sleep函數java

sleep函數主要用來作延遲執行的,不少編程語言都有sleep函數,可是javascript沒有這個函數,咱們實現一下:node

一、簡單版本git

function sleep(sleepTime){ for(var start = +new Date;+new Date - start<sleepTime;){} } var t1 = +new Date(); sleep(3000); var t2 = +new Date(); console.log(t2-t1);

優勢:簡單粗暴,通俗易懂。github

缺點:確實sleep了,可是卡死了,cpu會飆升,精確度不許編程

 

二、promise版本promise

// promise版本 function sleep(sleepTime){ return new Promise(resolve => setTimeout(resolve,sleepTime)); } var t1 = +new Date(); sleep(3000).then(()=>{ var t2 = +new Date(); console.log(t2-t1); }) 

優勢:實際上用了setTimeout,沒有造成進程阻塞,不會形成性能和負載問題。babel

缺點:雖然解決了回調函數的嵌套,可是仍是不美觀,並且異步不完全,過程當中中止執行。異步

 

三、generator版本

// generotor版本 function sleep(sleepTime){ return function(cb){ setTimeout(cb.bind(this), sleepTime); } } function* genSleep(){ var t1 = +new Date(); yield sleep(3000); var t2 = +new Date(); console.log(t2-t1); } async(genSleep); function async(gen){ const iter = gen(); function nextStep(it){ if(it.done) return ; if (typeof it.value === "function") { it.value(function(ret) { nextStep(iter.next(ret)) }) } else { nextStep(iter.next(it.value)); } } nextStep(iter.next()); }

優勢:跟promise同樣優勢,代碼變得更簡單幹淨。

缺點:就是每次都要執行 next() 顯得很麻煩,雖然有 co(第三方包)能夠解決,但就多包了一層,很差看,錯誤也必須按 co 的邏輯來處理,不爽。

co 之因此這麼火併非沒有緣由的,固然不是僅僅實現 sleep 這麼無聊的事情,而是它活生生的藉着generator/yield 實現了很相似 async/await 的效果!這一點真是讓我三觀盡毀另眼相看。

const co = require("co") function sleep(sleepTime) { return function(cb) { setTimeout(cb.bind(this), sleepTime) } } co(function*() { const t1 = +new Date() yield sleep(3000) const t2 = +new Date() console.log(t2 - t1) })

 

四、async/await版本

function sleep(delay) { return new Promise(reslove => { setTimeout(reslove, delay) }) } !async function test() { const t1 = +new Date() await sleep(3000) const t2 = +new Date() console.log(t2 - t1) }()

優勢:同 Promise 和 Generator 優勢。 Async/Await 能夠看作是 Generator 的語法糖,Async 和 Await 相較於 * 和 yield 更加語義,另外各個函數都是扁平的,不會產生多餘的嵌套,代碼更加清爽易讀。

缺點:ES7 語法存在兼容性問題,有 babel 一切兼容性都不是問題

 

五、開源的版本

在 javascript 優雅的寫 sleep 等於如何優雅的不優雅,這裏有 C++ 實現的模塊:https://github.com/ErikDubbelboer/node-sleep

const sleep = require("sleep") const t1 = +new Date() sleep.msleep(3000) const t2 = +new Date() console.log(t2 - t1)

優勢:可以實現更加精細的時間精確度,並且看起來就是真的 sleep 函數,清晰直白。
缺點:缺點須要安裝這個模塊node-sleep

 

前端知識點Async/Await是目前前端異步書寫最優雅的一種方式

 

2、優雅獲取時間戳

上面實現 sleep 函數,咱們能夠發現代碼有 +new Date()獲取時間戳的用法,這只是其中的一種,下面就說一下其餘兩種以及 +new Date()的原理。

一、普通版

var timestamp=new Date().getTime()

優勢:具備廣泛性,你們都用這個
缺點:應該沒有吧

 

二、進階版

var timestamp = (new Date()).valueOf()

valueOf 方法返回對象的原始值(Primitive,'Null','Undefined','String','Boolean','Number'五種基本數據類型之一),多是字符串、數值或 bool 值等,看具體的對象。

優勢:說明開發者原始值有一個具體的認知,讓人眼前一亮。
缺點: 應該沒有吧

 

三、Date.now()方法

Date.now()

Date.now() 方法返回自1970年1月1日 00:00:00 UTC到當前時間的毫秒數。類型爲Number。由於 now() 是Date的一個靜態函數,因此必須以 Date.now() 的形式來使用。

優勢:簡單明瞭。

缺點:兼容性問題,ECMA-262 第五版中被標準化。

兼容性不支持時的兼容性代碼:

if (!Date.now) { Date.now = function now() { return new Date().getTime(); }; }

 

四、終極版

var timestamp = +new Date()

優勢:對 JavaScript 隱式轉換掌握的比較牢固的一個表現
缺點:應該沒有吧

咱們來分析一下,爲何+new Date()拿到的時間戳?

那就是隱式轉換,實質上仍是調用了valueOf()的方法。

 

注意:

(1)一元+ 運算符

一元 + 運算符將其操做數轉換爲 Number 類型並反轉其正負。注意負的 +0 產生 -0,負的 -0 產生 +0

+new Date() 至關於 ToNumber(new Date())

 

(2)toString 用來返回對象的字符串表示。

var obj = {}; console.log(obj.toString());//[object Object] var arr = []; console.log(arr.toString());//""空字符串 var date = new Date(); // Tue May 28 2019 22:05:58 GMT+0800 (中國標準時間) console.log(date.toString());//"Tue May 28 2019 22:05:58 GMT+0800 (中國標準時間)"

 

(3)valueOf()方法返回對象的原始值

valueOf()方法返回對象的原始值,多是字符串,述職或boolean值,看具體的對象。

var obj = { name: "saucxs" } console.log(obj.valueOf()) //Object {name: "saucxs"} var arr1 = [1,3] console.log(arr1.valueOf()) //[1,3] var date = new Date() console.log(date.valueOf())//1456638436303 // 如代碼所示,三個不一樣的對象實例調用valueOf返回不一樣的數據

原始值指的是 'Null','Undefined','String','Boolean','Number','Symbol' 6種基本數據類型之一,上面已經提到過這個概念,這裏再次申明一下。

 

最後分解一下其中的過程:+new Date():    

(1)運算符 new 的優先級高於一元運算符 +,因此過程能夠分解爲:var time=new Date();+time

(2)根據上面提到的規則至關於:ToNumber(time)

(3)time 是個日期對象,根據 ToNumber 的轉換規則,因此至關於:ToNumber(ToPrimitive(time))

(4)根據 ToPrimitive 的轉換規則:ToNumber(time.valueOf()),time.valueOf() 就是 原始值 獲得的是個時間戳,假設 time.valueOf()=1503479124652

(5)因此 ToNumber(1503479124652) 返回值是 1503479124652 這個數字。

前端知識點:隱式轉換的妙用

相關文章
相關標籤/搜索