microtasks、macrotasks与函数柯里化

1、microtasks、macrotasks

JavaScript是单线程执行的,而现在推行的多线程执行,都可以理解为伪多线程,因为所有的执行都会回归的主线程执行,

而主线程外会有如多个消息队列,等待主线程的空闲后进入执行。

而microtasks与macrotasks就是很好理解事件环的概念,然后它在不同的浏览器的执行顺序可能不一致,但不妨去理解它。

V8实现中,两个队列各包含不同的任务:

macrotasks: script(整体代码),setTimeout, setInterval, setImmediate, I/O, UI rendering

microtasks: process.nextTick, Promises, Object.observe, MutationObserver

在现在浏览器中可能使用到就script(整体代码),setTimeout,setInterval,UI rendering,Promises等,而其他可能不常用,如果是nodeJs可能就常用。

资料一

资料二

从资料中可以知道microtasks这个是会阻塞浏览器渲染的,因为它是在主线程一空闲下来就执行,而macrotasks就是在浏览器渲染后再执行,可以利用

这一特性有效的提高性能,如vue里的nextTick就是触发microtasks,那么就可以实现多线程执行且浏览器渲染阻塞等待处理后执行来提高性能,而不是

每次的更新都要执行渲染,那样会很消耗性能,但microtasks的执行会比事件冒泡都要优先,所以这里就会出现事件触发后当前事件执行了,后就执行

microtasks里的,然后再执行冒泡,所以还要把事件强制为macrotasks,而vue就是这样的处理逻辑。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    #a{
        width: 200px;
        height: 200px;
        background: #000;
    }
    #b{
        width: 100px;
        height: 100px;
        background: #ff7600;
    }
    </style>
</head>
<body>
    <div id="a">
        <div id="b"></div>
    </div>

<script>

var a = document.querySelector("#a");
var b = document.querySelector("#b");

a.onclick = function(){
    console.log("a");
}
b.onclick = function(){
    pp();
    console.log("b");
}

function pp(){
    setTimeout(function(){
        console.log("timeout");
    },0);
    new Promise(function(resolve){
        console.log("Promise");
        resolve();
    }).then(function(){
        console.log("then");
    });
}

</script>
</body>
</html>

结果:
Promise
b
then
a
timeout

从上例子可知,microtasks真的厉害。。。。也证实的以上概念。

2、函数柯里化

把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

这增加了函数的适用性,但同时也降低了函数的适用范围。

资料一

函数柯里化工具方法实现:

一:

function curry(){
    var args = [].slice.call(arguments);
    var fnLen = 0;
    var fn = args[0];
    if(typeof fn !== ‘function‘){
        console.error(‘first param is not function!‘);
        return null;
    }
    fnLen = fn.length;
    args.shift();
    if(args[0] instanceof Array){
        args = args[0];
    }
    return function(){
        var _args = [].slice.call(arguments);
        [].push.apply(args,_args);
        if(args.length >= fnLen){
            return fn.apply(this, args);
        }
        return arguments.callee
    }
}

// 例子一
function fb(a,b,c,d,e,f,g){
    console.log([].slice.call(arguments));
}

fb = curry(fb,[10,20,30,40]);
console.log(fb(50)(60)(70));

fb = curry(fb);
console.log(fb(10)(20)(30)(40)(50)(60)(70));

// 例子二
function fss(v,b,n,m,x){
    console.log([].slice.call(arguments));
}
fss = curry(fss,107,270,307,407);
console.log(fss(50));

此方法为只有被柯里化的函数的参数全部传递后才能执行函数,而参数传递完后还调用就会报错。

二:

function curry(){
    var args = [].slice.call(arguments);
    var fn = args[0];
    if(typeof fn !== ‘function‘){
        console.error(‘first param is not function!‘);
        return null;
    }
    args.shift();
    if(args[0] instanceof Array){
        args = args[0];
    }
    return function(){
        var _args = [].slice.call(arguments);
        [].push.apply(args,_args);

        arguments.callee.valueOf = function(){
            return fn.apply(this, args);
        }

        return arguments.callee;
    }
}

function fss(v,b,n,m,x){
    console.log([].slice.call(arguments));
}
fss = curry(fss,107,270,307,407);
console.log(fss(50)(30)(100)(1000));

这种柯里化使用的隐形转换toString,valueOf等实现,因为转换在函数调用的最后一步执行,此可以实现无限传参,无参数长度的限制。

柯里化是为了让函数的自由度增大,但也牺牲了一些性能,但在一些封装里会让代码更加顺畅,且优雅,因为一些重复代码可以省略。

原文地址:https://www.cnblogs.com/zhangzhicheng/p/9840410.html

时间: 2024-08-28 17:21:06

microtasks、macrotasks与函数柯里化的相关文章

建议75:函数柯里化

柯里化是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回一个新函数,这个新函数能够接受原函数的参数.下面可以通过例子来帮助理解.function adder(num) {    return function(x) {        return num + x;    }}var add5 = adder(5);var add6 = adder(6);print(add5(1));  // 6print(add6(1));  //7 函数adder接受一个参数,并返回一个函数,这个返

【前端学习笔记】函数柯里化(自网易云课堂)

1. 函数柯里化通常是指把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的并且返回一个接受余下的参数而且返回结果的新函数的技术. // 1. 最简单的柯里化 // sum函数接受三个参数,并返回求和结果 var sum = function(a,b,c) { return a+b+c; } // 最简单柯里化的sum函数 var sum_curry = function(a){ return function(b,c){ return a+b+c; } } 2. 更泛化的定义是

【读书笔记】 函数柯里化

这是书上函数柯里化的例子 1 function curry(fn){ 2 var args = Array.prototype.slice.call(arguments, 1);//取出调用curry时除了第一个函数参数的后面所有参数; 3 return function(){ 4 var innerArgs = Array.prototype.slice.call(arguments);//取出第二次调用时的所有参数; 5 var finalArgs = args.concat(innerAr

一道javascript面试题(闭包与函数柯里化)

要求写一个函数add(),分别实现能如下效果: (1)console.log(add(1)(2)(3)(4)());//10 (2)console.log(add(1,2)(3,4)());//10 (3)console.log(add(1,2)(3,4));//10 针对(1)和(2),有两种思路实现:纯闭包思路和函数柯里化思路.一.闭包思路 (1)的解决方案(闭包实现) function add(arg) { // body... let sum = 0; sum+=arg; return

JavaScript函数柯里化的一些思考

1. 高阶函数的坑 在学习柯里化之前,我们首先来看下面一段代码: var f1 = function(x){ return f(x); }; f1(x); 很多同学都能看出来,这些写是非常傻的,因为函数f1和f是等效的,我们直接令var f1 = f;就行了,完全没有必要包裹那么一层. 但是,下面一段代码就未必能够看得出问题来了: var getServerStuff = function(callback){ return ajaxCall(function(json){ return cal

【转载】JS中bind方法与函数柯里化

原生bind方法 不同于jQuery中的bind方法只是简单的绑定事件函数,原生js中bind()方法略复杂,该方法上在ES5中被引入,大概就是IE9+等现代浏览器都支持了(有关ES5各项特性的支持情况戳这里ECMAScript 5 compatibility table),权威指南上提到在ES3中利用apply模拟该方法的实现(JS权威指南中函数那章), 但无法真实还原该方法, 这也是真bind方法中的有趣特性. (原文这边理解有问题, 这段话的意思如果结合犀牛书上下文的意思, 再结合犀牛书中

[转]js函数式变成之函数柯里化

本文转自:https://segmentfault.com/a/1190000003733107 函数柯里化是指参数逐渐求值的过程. 我觉得它是:降低通用性,提高专用性. 通常,柯里化是这样的过程,“如果你固定某些参数,你将得到接受余下参数的一个函数”.所以对于有两个变量的函数y^x,如果固定了 y=2,则得到有一个变量的函数 2^x 通用实现 全选复制放进笔记 function currying(fn) { var slice = Array.prototype.slice; var args

函数柯里化or not

今天leader说需要写一个通用函数,可以实现在不同的情况下都可以仅调用这一函数,而只是传递参数不同,我首先想到的是函数柯里化,实现把不同的参数转化成单一参数的方式,于是,利用了常见的函数柯里化方式并加以改造,利用了我们最常见的参数对象arguments,然后在总函数中写了arguments[1],arguments[2]来实现功能,自我感觉好像还不错. 但是leader看了代码说不行,不利于开发,为什么呢. 我改造的函数柯里化有一定局限性,尽管这个arguments[1]的值并不确定,但是这个

Swift函数柯里化(Currying)简谈

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 下面简单说说Swift语言中的函数柯里化简单的说就是把接收多个参数的函数划分为若干个"嵌套"的单一参数的函数. 这样说谁也听不懂,我们结合一个例子给大家简单说说. 我们需要定义一个函数A,该函数返回一个函数B,函数B创建一只大蜘蛛.为什么要间接返回大蜘蛛,因为本猫最怕大蜘蛛,所以不敢直接返回大蜘蛛 ;) 首先是蜘蛛的类: class Spider:C