JavaScript 最新特性实现的三大黑科技

有时候,我们希望批量执行一组异步任务,但是不是并行,而是依次执行,这组任务是动态的,在一个数组里,当然我们可以用 for 循环然后一个一个 await 执行,但是还有另外一种方式:

JS Bin on jsbin.com

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

async function taskReducer(promise, action){

let res = await promise;

return action(res);

}

function sleep(ms){

return new Promise(resolve => setTimeout(resolve, ms));

}

async function asyncTask(i){

await sleep(500);

console.log(`task ${i} done`);

return ++i;

}

[asyncTask, asyncTask, asyncTask].reduce(taskReducer, 0);

在上面的例子里,我们定义了一个 taskReducer:

1

2

3

4

async function taskReducer(promise, action){

let res = await promise;

return action(res);

}

这个 reducer 的两个参数是 promise 和 action,promise 是代表当前任务的 promise,而 action 是下一个要执行的任务。我们可以 await 当前 promise 执行当前任务,然后将执行结果传给下一个 action 就可以了。

这样我们可以调用:

1

[task1, task2, task3, ...].reduce(taskReducer, init);

不管这些任务是同步还是异步都可以被依次执行。需要注意的是,每一个任务的返回值将是下一个任务的输入 promise 或者 value。

generator 与 async/await 一同使用

将上面的代码进一步扩展,我们发现,它可以支持 generator 与 async/await 一同使用:

JS Bin on jsbin.com

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

async function reducer(promise, action){

let res = await promise;

return action(res);

}

function tick(i){

console.log(i);

return new Promise(resolve => setTimeout(()=>resolve(++i), 1000));

}

function continuous(...functors){

return async function(input){

return await functors.reduce(reducer, input)

}

}

function * timing(count = 5){

for(let i = 0; i yield tick;

}

}

continuous(...timing(10))(0);

在上面的例子里,我们定义了一个计时 tick 函数,我们通过 timing 来连续调用它,而 timing 是一个 generator,计时器显然是异步函数,然而我们可以:

1

continuous(...timing(10))(0);

而这里的 continuous 其实就是前面的 reduce 的封装。

使用 Proxy 实现 PHP 中的常用“魔术方法”

PHP 中有 __get 、 __set 和 __call 三个强大的魔术方法,可以实现对不存在的属性的读写和方法调用。在新的 ES 标准中添加了 Proxy 类,它可以构造 Proxy 对象,用来“重载”对象的属性和方法读写,从而实现类似于 PHP 的魔术方法:

JS Bin on jsbin.com

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

function Magical(Class){

return function(...args){

return new Proxy(new Class(...args), {

get: function(target, key, receiver) {

if(typeof target[key] !== ‘undefined‘){

return target[key];

}

if (typeof target.__get === ‘function‘){

return target.__get(key);

} else if (typeof target.__call === ‘function‘) {

return function(...args){

target.__call.apply(this, [key, ...args]);

};

}

},

set: function(target, key, value, receiver){

if(typeof target[key] !== ‘undefined‘){

target[key] = value;

return;

}

if (typeof target.__set === ‘function‘){

target.__set(key, value);

return;

}

}

});

}

}

class Foo{

__set(key, value){

this[key] = value * 2;

}

__get(key){

return this.b;

}

__call(key, ...args){

console.log(`call method ${key} with ${args}`);

}

b(...args){

console.log(`b exists: ${args}`);

}

}

Foo = Magical(Foo);

var f = new Foo();

f.b(1,2,3);

f.a(4,5,6);

f.c = 3;

console.log(f.c);

上面的例子里,我们在对象构造的时候,分别“代理”对象实例的属性 get 和 set 方法,如果对象上已存在某个属性或方法,代理直接返回或操作该属性。否则,判断对象上是否有 __get、__set 或者 __call 方法,有的话,做相应的处理。

这里我们使用装饰器模式,定义了一个 Magical 装饰器函数,让它来处理希望使用 Magical 的类。

等到 ES Decorators 标准化了之后,我们就可以使用更加优雅的写法了:

1

2

3

4

5

6

@magical

class Foo {

__call(key, ...args){

...

}

}

有时候,我们希望批量执行一组异步任务,但是不是并行,而是依次执行,这组任务是动态的,在一个数组里,当然我们可以用 for 循环然后一个一个 await 执行,但是还有另外一种方式:

JS Bin on jsbin.com

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

async function taskReducer(promise, action){

let res = await promise;

return action(res);

}

function sleep(ms){

return new Promise(resolve => setTimeout(resolve, ms));

}

async function asyncTask(i){

await sleep(500);

console.log(`task ${i} done`);

return ++i;

}

[asyncTask, asyncTask, asyncTask].reduce(taskReducer, 0);

在上面的例子里,我们定义了一个 taskReducer:

1

2

3

4

async function taskReducer(promise, action){

let res = await promise;

return action(res);

}

这个 reducer 的两个参数是 promise 和 action,promise 是代表当前任务的 promise,而 action 是下一个要执行的任务。我们可以 await 当前 promise 执行当前任务,然后将执行结果传给下一个 action 就可以了。

这样我们可以调用:

1

[task1, task2, task3, ...].reduce(taskReducer, init);

不管这些任务是同步还是异步都可以被依次执行。需要注意的是,每一个任务的返回值将是下一个任务的输入 promise 或者 value。

generator 与 async/await 一同使用

将上面的代码进一步扩展,我们发现,它可以支持 generator 与 async/await 一同使用:

JS Bin on jsbin.com

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

async function reducer(promise, action){

let res = await promise;

return action(res);

}

function tick(i){

console.log(i);

return new Promise(resolve => setTimeout(()=>resolve(++i), 1000));

}

function continuous(...functors){

return async function(input){

return await functors.reduce(reducer, input)

}

}

function * timing(count = 5){

for(let i = 0; i yield tick;

}

}

continuous(...timing(10))(0);

在上面的例子里,我们定义了一个计时 tick 函数,我们通过 timing 来连续调用它,而 timing 是一个 generator,计时器显然是异步函数,然而我们可以:

1

continuous(...timing(10))(0);

而这里的 continuous 其实就是前面的 reduce 的封装。

使用 Proxy 实现 PHP 中的常用“魔术方法”

PHP 中有 __get 、 __set 和 __call 三个强大的魔术方法,可以实现对不存在的属性的读写和方法调用。在新的 ES 标准中添加了 Proxy 类,它可以构造 Proxy 对象,用来“重载”对象的属性和方法读写,从而实现类似于 PHP 的魔术方法:

JS Bin on jsbin.com

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

function Magical(Class){

return function(...args){

return new Proxy(new Class(...args), {

get: function(target, key, receiver) {

if(typeof target[key] !== ‘undefined‘){

return target[key];

}

if (typeof target.__get === ‘function‘){

return target.__get(key);

} else if (typeof target.__call === ‘function‘) {

return function(...args){

target.__call.apply(this, [key, ...args]);

};

}

},

set: function(target, key, value, receiver){

if(typeof target[key] !== ‘undefined‘){

target[key] = value;

return;

}

if (typeof target.__set === ‘function‘){

target.__set(key, value);

return;

}

}

});

}

}

class Foo{

__set(key, value){

this[key] = value * 2;

}

__get(key){

return this.b;

}

__call(key, ...args){

console.log(`call method ${key} with ${args}`);

}

b(...args){

console.log(`b exists: ${args}`);

}

}

Foo = Magical(Foo);

var f = new Foo();

f.b(1,2,3);

f.a(4,5,6);

f.c = 3;

console.log(f.c);

上面的例子里,我们在对象构造的时候,分别“代理”对象实例的属性 get 和 set 方法,如果对象上已存在某个属性或方法,代理直接返回或操作该属性。否则,判断对象上是否有 __get、__set 或者 __call 方法,有的话,做相应的处理。

这里我们使用装饰器模式,定义了一个 Magical 装饰器函数,让它来处理希望使用 Magical 的类。

等到 ES Decorators 标准化了之后,我们就可以使用更加优雅的写法了:

1

2

3

4

5

6

@magical

class Foo {

__call(key, ...args){

...

}

}

本文源于 www.71key.com

时间: 2024-11-05 20:46:09

JavaScript 最新特性实现的三大黑科技的相关文章

【高热度网】2020年最新8款迷你世界手机黑科技辅助软件免费下载

迷你世界黑科技是网络上一个比较火热的热词,迷你世界黑科技怎么做呢?如何在安卓手机APP实现迷你世界的黑科技呢?通过下载今天分享的这8款手机版迷你世界黑科技地图和皮肤装备辅助软件,你就可以全部实现. 迷你世界最新版本的黑科技,你知道多少? 迷你世界游戏简介: 迷你世界是一款高度自由的3D沙盒游戏,玩家可以自由创建城堡.房屋.桥梁等各式各样的城市建筑物,打造一个自己理想中的迷你世界.分享的这最新8款辅助APP,用户可以拥有无限皮肤.无限装备.迷你币修改.经验无限增加.黑科技地图等多种炫酷好玩的黑科技

【转】这些JavaScript编程黑科技,装逼指南,高逼格代码,让你惊叹不已

[转]这些JavaScript编程黑科技,装逼指南,高逼格代码,让你惊叹不已 Javascript是一门很吊的语言,我可能学了假的JavaScript,哈哈,大家还有什么推荐的 本文秉承着:你看不懂是你SB,我写的代码就要牛逼. 1.单行写一个评级组件 "★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate);定义一个变量rate是1到5的值,然后执行上面代码,看图 才发现插件什么的都弱爆了 2.如何装逼用代码骂别人SB (!(~+[])+{})[--[~+&qu

聊聊H5与JS近几年的黑科技

聊聊H5与JS近几年的黑科技 自ajax技术的诞生,编程界兴起了一股WEB开发热,facebook,Twitter等众多大佬级企业都在网页应用上大放异彩,这十年我们见证了前端技术的崛起.这期间产生了众多脱离了浏览器的JS和H5开发的黑科技.移动端的react native,cordova,native.js:PC端的Node.js,NW.js:当然还有前端本身的众多框架,vue.js,jquery.js,bootstrap等等. 所以JS不再是一门单纯的浏览器脚本,作为一个前端开发者如果跟不上前

2017黑科技趋势最具看点的十大新品

腾讯数码讯(Human)作为一年一度的全球消费电子市场风向标,今年同样在拉斯维加斯举办的CES 2017消费电子展,依然吸引了一大批全球各个领域的厂商参展,从科技巨头到初创小团队.从传统汽车厂商再到家电企业,似乎所有能与科技沾边的公司都希望能在CES 2017上好好展示一次自己的风采. 其实每年的CES都有一些明星产品给我们留下深刻的印象,今年的也不例外.而这些明星产品不仅仅只是单单一款产品,更是代表了各自行业在进入到2017年之后的一个发展趋势和方向.而就将这样的变化能否成为未来的主流.或只是

今年数博会全面升级!BAT+TMD+ABC黑科技,你能看到谁?

一年一度的贵阳数博会又要来了!2017年5月26-29日,第三届贵阳数博会将在贵阳举办.然后重要的事情说三遍,今年的数博会规格全面升级了!升级了!升级了!今年数博会是首届中国国际大数据产业博览会,本届数博会的年度主题为"数字经济引领新增长". 2015年,数博会第一次举办的时候叫贵阳国际大数据产业博览会暨全球大数据时代贵阳峰会分,2016年第二次举办的时候叫中国大数据产业峰会暨中国电子商务创新发展峰会,2017年正式升级为中国国际大数据产业博览会,这意味着2017年数博会正式升级为国家

今年黑科技趋势最具的五个看点

CES 2017年人工智能引爆全球最火黑科技盛会 CES 2017 1月5日-8日在美国拉斯维加斯举行,数千家企业.几十万人将参与到这次科技的狂欢秀中.本文为埃森哲技术总监带来的关于本年度CES 的5大看点.他认为:人工智能将统治本年度的CES,变得无处不在.另外,他还分析了智能助理.物联网安全.虚拟现实等多个领域在本届大会上的表现. 2017 年国际消费电子展(CES 2017)将于1月5号拉开帷幕,在这个荒漠之城举办为期5天的展会,保守估计会吸引超过177000名参会者. 这也是一年之中唯一

市值超越高通后,NVIDIA用黑科技抢占苹果高端笔记本市场

(上图为NVIDIA CEO黄仁勋在2017台北Computex上介绍Max-Q设计) 2011年10月21日,NVIDIA CEO黄仁勋在AsiaD大会上表示,高通是该公司最为直接的竞争对手,苹果公司是间接竞争对手.6年后,在2017年5月30日的台北电脑展Computex期间,NVIDIA的市值超过了高通,当天NVIDIA的总市值达854.70亿美元,而高通的总市值则是851.01亿美元. 在第二天接受记者采访的时候,黄仁勋表示了一下惊讶:"是吗?"接着就继续讲在本次台北Compu

竖亥——京东以神为名出击,神一样的物流黑科技

曾经,一谈起快递.物流,第一反应就是劳动密集型行业,跟信息化.高科技几乎没有任何关系,更不会与代表科技前沿与未来想象的黑科技出现交集.但继亚马逊对黑科技没有门也要爬窗进的执着追求后,京东也开始研究.应用黑科技了.竖亥项目是京东联合英特尔,利用英特尔RealSense技术和京东强大的软件开发能力,全新推出的应用于仓储商品物流属性的自动采集项目. 自动采集取代人工操作 首先看下竖亥小车如何取代人工操作: 如图所示,这个自动采集必备的竖亥小车由车体.深度传感器.电脑或者平板的显示屏.玻璃底板以及附加的

C++的黑科技(深入探索C++对象模型)

周二面了腾讯,之前只投了TST内推,貌似就是TST面试了 其中有一个问题,“如何产生一个不能被继承的类”,这道题我反反复复只想到,将父类的构造函数私有,让子类不能调用,最后归结出一个单例模式,但面试官说,单例模式作为此题的解答不够灵活,后来面试官提示说,可以用友元+虚继承,可以完美实现这样一个类 当然那时我还不太明白,友元与虚继承我都极少接触过,只是知道有这些东西,回头搜了一下“不能被继承的类”的做法,具体如下: 1,声明一个类,CNoHeritance,构造函数为private,并声明友元类C