JavaScript 系列

Stella981
• 阅读 459

一、前言

有些东西很好用,但是你未必知道;有些东西你可能用过,但是你未必知道原理。
实现一个目的有多种途径,俗话说,条条大路通罗马。发散一下大家的思维以及拓展一下知识面。

二、实现一个简短的sleep函数

sleep函数主要用来做延迟执行的,很多编程语言都有sleep函数,但是javascript没有这个函数,我们实现一下:

1、简单版本

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);

优点:简单粗暴,通俗易懂。

缺点:确实sleep了,但是卡死了,cpu会飙升,精确度不准

2、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,没有形成进程阻塞,不会造成性能和负载问题。

缺点:虽然解决了回调函数的嵌套,但是还是不美观,而且异步不彻底,过程中停止执行。

3、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) })

4、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 一切兼容性都不是问题

5、开源的版本

在 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是目前前端异步书写最优雅的一种方式

二、优雅获取时间戳

上面实现 sleep 函数,我们可以发现代码有 +new Date()获取时间戳的用法,这只是其中的一种,下面就说一下其他两种以及 +new Date()的原理。

1、普通版

var timestamp=new Date().getTime()

优点:具有普遍性,大家都用这个
缺点:应该没有吧

2、进阶版

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

valueOf 方法返回对象的原始值(Primitive,'Null','Undefined','String','Boolean','Number'五种基本数据类型之一),可能是字符串、数值或 bool 值等,看具体的对象。

优点:说明开发者原始值有一个具体的认知,让人眼前一亮。
缺点: 应该没有吧

3、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(); }; }

4、终极版

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 这个数字。

前端知识点:隐式转换的妙用

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Stella981 Stella981
3年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Wesley13 Wesley13
3年前
PHP中的NOW()函数
是否有一个PHP函数以与MySQL函数NOW()相同的格式返回日期和时间?我知道如何使用date()做到这一点,但是我问是否有一个仅用于此的函数。例如,返回:2009120100:00:001楼使用此功能:functiongetDatetimeNow(){
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这