hujiejeff/hujiejeff.github.io

你不知道的JavaScript(中)笔记

Opened this issue · 3 comments

你不知道的JavaScript(中)笔记

Web Worker

what

提供一种多线程的运行方式
通过创建web worker创建一个在后台线程运行的js程序

how

通过发送消息和监听消息完成主线程和worker线程的通讯

//主线程加载另一个文件
let worker = new Worker("./worker.js");

//添加消息监听

worker.addEventListener("message", ev => {
          console.log(ev);
          console.log("idnex page is received");
          let p = document.createElement("p");
          p.innerText = "idnex page is received";
          console.log(ev.data);
          app.appendChild(p);
        });

//发送消息
worker.postMessage("hello");

在worker.js中

console.log(this);
this.addEventListener("message", ev => {
  console.log(ev);
  console.log("worker is received");
  this.postMessage("halo");
});

尾调用

函数调用于与返回实际上一个栈帧的入栈和出栈,如果在return 语句仅进行函数调用,栈帧得到复用,节省了内存以及后续大量的入栈出栈时间。

what

尾部直接调用另一函数,不在函数调用外进行运算。这样进行尾调用时,栈帧得以复用。在递归场景下,使用尾递归优化可以实现很好的性能优化

function f1(a) {

}

function f2() {
  //do something
  let a = 10;
  return f1(a + 10);//尾调用
}

function f3() {
  let a = 10;
  return f3(a) + 10;//非尾调用
}

比如打印一个斐波那契数列

糟糕的实现

function f(n) {
    if (n < 0) {
        return 0;
    }
    if (n === 0 || n === 1) {
        return 1;
    }
    return f(n - 1) + f(n - 2);
}

这种状况下返回时,除了本身的栈帧,然后又会压入f(n-1) 和f(n-2),两个栈帧,然后递归中又是压入n多个栈帧。

尾递归优化

function fibonacci(n) {
    function fib(n, v1, v2) {
        if (n == 1)
            return v1;
        if (n == 2)
            return v2;
        else
            return fib(n - 1, v2, v1 + v2)
    }
    return fib(n, 1, 1)
}
fibonacci(30)

简易版Promise实现

class MyPromise {
    status = 'pending';
    data;
    constructor(executor) {
        executor(this.resolve.bind(this), this.reject.bind(this));
    }
    then(onSucessCallback, onFailedCallback) {
        return new MyPromise((resolve, reject) => {
            if (this.status === 'resolved') {
                //状态完成,直接执行
                setTimeout(() => {
                    resolve(onSucessCallback(this.data));
                });
            } else if (this.status === 'rejected') {
                //状态完成,直接执行
                setTimeout(() => {
                    reject(onFailedCallback(this.data));
                });
            } else if (this.status === 'pending') {
                //状态准备,启用回调
                this.onSucessCallback = (res) => {
                    resolve(onSucessCallback(res));
                };
                this.onFailedCallback = (err) => {
                    reject(onFailedCallback(err));
                };
            }
        });


    }
    resolve(res) {

        if (this.status === 'pending') {
            this.data = res;
            this.status = 'resolved';
            if (typeof this.onSucessCallback === 'function') {
                setTimeout(() => this.onSucessCallback(res), 0);
            }
        }
    }
    reject(err) {
        if (this.status === 'pending') {
            this.data = err;
            if (typeof this.onFailedCallback === 'function') {
                setTimeout(() => this.onFailedCallback(err), 0)
            }
        }
    }
    static all(...promises) {
        let sucessCount = 0;
        let hasErrCalled = false;
        let results = [];
        return new MyPromise((resovle, reject) => {
            for (let promise of promises) {
                promise.then(res => {
                    results.push(res);
                    sucessCount++;
                    if (sucessCount === promises.length) {
                        resovle(results);
                    }
                }, err => {
                    if (!hasErrCalled) {
                        hasErrCalled = true;
                        reject(err);
                    }
                });
            }
        });
    }
}