[记录]我的日常随笔(三)

简介: [记录]我的日常随笔(三)
  1. 深拷贝
// 小细节 -> 需要考虑一下循环引用的情况 -> WeakMap
function deepCopy(obj){
    let result;
    if(typeof obj == "object"){
        //复杂数据类型
       result = obj.constructor == Array ? [] : {};
        for(let i in obj){
            result[i] = typeof obj[i] == "object" ? deepCopy(obj[i]) : obj[i];
        }
    }else {
       result = obj;
    }
    return result;
}

function deepCopy2(target, weakMaps = new WeakMap()) {
  if (typeof target !== "object" || target === null) {
    return target;
  }
  if (weakMaps.has(target)) return weakMaps.get(target);
  const res = Array.isArray(target) ? [] : {};
  weakMaps.set(target, res);
  for (let key in target) {
    res[key] = deepCopy(target[key], weakMaps);
  }
  return res;
}

21.浏览器进程与线程
https://imweb.io/topic/58e3bfa845e5c13468f567d5

22.设计一个简单的任务队列,要求分别在 1,3,4 秒后打印出”1“,”2“,”3“

/**
 * 题目
 */
new Quene()
  .task(1000, () => {
    console.log(1);
  })
  .task(2000, () => {
    console.log(2);
  })
  .task(1000, () => {
    console.log(3);
  })
  .start();

function Quene() { ... }

/**
 * 解题1 promise
 */
class Quene {
  constructor() {
    this.tasks = [];
  }
  task(wait, fn) {
    this.tasks.push({
      wait,
      fn,
    });
    return this;
  }
  async start() {
    for (let task of this.tasks) {
      const { wait, fn } = task;
      await new Promise((res, rej) => {
        setTimeout(() => {
          fn();
          res();
        }, wait);
      });
    }
  }
}

/**
 * 解题2 递归
 */
class Quene {
  constructor() {
    this.tasks = [];
  }
  task(wait, fn) {
    this.tasks.push({ wait, fn });
    return this;
  }
  start() {
    const firstTask = this.tasks.shift();
    if (firstTask) {
      setTimeout(() => {
        firstTask.fn();
        this.start();
      }, firstTask.wait);
    }
  }
}

/**
 * 解题3 闭包
 */
class Queue {
  constructor() {
    this.tasks = [];
  }
  task(wait, fn) {
    this.tasks.push({
      wait,
      fn,
    });
    return this;
  }
  start() {
    let int = 0;
    this.tasks.forEach(({ wait, fn }) => {
      setTimeout(() => {
        fn();
      }, (int += wait));
    });
  }
}
  1. 用 setTimeout 实现 setInterval,阐述实现的效果与 setInterval 的差异
function mySetInterval(fn, wait) {
    mySetInterval.timer = setTimeout(() => {
        fn();
        mySetInterval(fn, wait);
    }, wait)
}

mySetInterval.clear = function() {
    clearTimeout(mySetInterval.timer)
}

mySetInterval(() => {
    console.log(11111)
}, 1000)

setTimeout(() => {
    // 5s 后清理
    mySetInterval.clear()
}, 5000)
  1. vue3 中的数据侦测
const rawToReactive = new WeakMap();
const reactiveToRaw = new WeakMap();

/**
 * utils
 * */
function isObject(val) {
  return typeof val === "object";
}
function hasOwn(val, key) {
  const hasOwnProperty = Object.prototype.hasOwnProperty;
  return hasOwnProperty.call(val, key);
}

/**
 * traps
 * */
// get
function createGetter() {
  return function(target,key,receiver) {
    const res = Reflect.get(target,key,receiver);
    console.log('get', key);
    return isObject(res) ? reactive(res) : res;
  }
}
// set
function set(target,key,value,receiver) {
  const hadKey = hasOwn(target, key);
  const oldValue = target[key];
  value = reactiveToRaw.get(value) || value;
  const res = Reflect.set(target, key, value, receiver)
  if(!hadKey || value !== oldValue) {
    console.log('tigger...');
  }
  return res;
}
// handle
const mutableHandlers = {
  get: createGetter(),
  set: set
};
// create reactive object
function createReactiveObject(target, toProxy, toRaw, baseHandlers) {
  let observed = toProxy.get(target);
  // target 生成过 observed,返回 observed
  if(observed !== void 0) {
    return observed;
  };
  // target 是 observed, 返回 target
  if(toRaw.has(target)) {
    return target;
  }
  observed = new Proxy(target, baseHandlers);
  toProxy.set(target, observed);
  toRaw.set(observed, target);
  return observed;
}
// enter
function reactive(target) {
  return createReactiveObject(target, rawToReactive, reactiveToRaw, mutableHandlers)
}
  1. Vue 的响应式原理中 Object.defineProperty 有什么缺陷?为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?
  • 优缺点

    1. Object.defineProperty 无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
    2. Object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy 可以劫持整个对象,并返回一个新的对象。
    3. Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
  1. 实现 async await
function co(genFun) {
    return new Promise((resolve, reject) => {
        const gen = genFun();
        function next(...params){
            const {value, done} = gen.next(...params);
            if(done){
                return resolve(value)
            } else {
                value.then((...args)=>next(...args));
            }
        };
        next();
    })
};
// test
const getData = () => new Promise(resolve => setTimeout(() => resolve("data"), 1000));
function* testG() {
  // await被编译成了yield
  const data = yield getData()
  console.log('data: ', data);
  const data2 = yield getData()
  console.log('data2: ', data2);
  return 'success'
}
co(testG).then(res=>{console.log('res', res)});
// logs
data:  data
data2:  data
res success
  1. LazyMan
// 实现LazyMan
LazyMan('jack').sleep(3000).eat('篮球').eat('rap').eat('唱、跳')
// hi,I'm jack
// 阻塞3s
// 篮球
// rap
// 唱、跳

LazyMan('x1').eat('高').sleep(5000).eat('富').eat('帅')
// hi,I'm x1
// 高
// 阻塞5s
// 富
// 帅

LazyMan('lurenjia').sleepFirst(3000).eat('吹').eat('牛')
// 阻塞3s
// hi,I'm lurenjia
// 吹
// 牛

class CraeteLazyMan {
  constructor(name) {
    this.queue = [];
    const nameTask = () => {
      console.log(`ADI-LOG => name`, name);
      this.task();
    };
    this.queue.push(nameTask);
    setTimeout(() => {
      this.task();
    }, 0);
  }
  task() {
    const fun = this.queue.shift();
    fun && fun();
  }
  sleep(time) {
    const _task = () => {
      setTimeout(() => {
        this.task();
      }, time);
    };
    this.queue.push(_task);
    return this;
  }
  sleepFirst(time) {
    const _task = () => {
      setTimeout(() => {
        this.task();
      }, time);
    };
    this.queue.unshift(_task);
    return this;
  }
  eat(str) {
    const _task = () => {
      console.log(`ADI-LOG => eat`, str);
      this.task();
    };
    this.queue.push(_task);
    return this;
  }
}

function LazyMan(name = "") {
  return new CraeteLazyMan(name);
}

  1. JS实现一个带并发控制的异步调度器,保证同时运动的任务最多有两个,完善下面代码

// https://github.com/Yuanyuanyuanc/aYuan-learning-notes/issues/2

class Scheduler {
  constructor(limt = 2) {
    this.limt = limt;
    this.queue = [];
    this.count = 0;
  }
  add(promiseCreator) {
    let resolve;
    const p = new Promise((res) => {
      resolve = res;
    });
    this.queue.push(() => promiseCreator().then(resolve));
    this.run();
    return p;
  }
  run() {
    if (this.count < this.limt && this.queue.length) {
      this.count++;
      const f = this.queue.shift();
      f().then(() => {
        this.count--;
        this.run();
      });
    }
  }
}
var timeout = (time) =>
  new Promise((resolve) =>
    setTimeout(() => {
      resolve();
      console.log(`ADI-LOG => time`, time);
    }, time)
  );
var scheduler = new Scheduler();
var addTask = (time, order) => {
  scheduler.add(() => timeout(time)).then(() => console.log(order));
};
addTask(1000, "1");
addTask(500, "2");
addTask(300, "3");
addTask(400, "4");
// 2314

addTask(0, 1);
addTask(2000, 2);
addTask(0, 3);
addTask(3000, 4);
addTask(0, 5);
// 13254
目录
相关文章
|
7月前
|
JavaScript
js事件记录(如有更新请留言我去补充)
js事件记录(如有更新请留言我去补充)
|
7月前
|
存储 关系型数据库 MySQL
MySql基础概念(随笔/小记)
MySql基础概念(随笔/小记)
42 0
Excel的实用操作记录,将持续更新
在工作中会遇到操作数据的时候,特别是在对数据的时候。vlookup、数据去重、检查重复项等功能是十分好用的
105 0
Excel的实用操作记录,将持续更新
|
负载均衡 Go
easycar更新日记
easycar更新日记
102 0
easycar更新日记
|
消息中间件 缓存 Kafka
【随笔】学习记录、实用脚本
文章目录 工作随笔 一、kafka 1.1 基础命令 二、es 1.1 基础命令 三、实用小脚本 3.1 判断文件中是否有某个对应的值
109 0
【随笔】学习记录、实用脚本
|
编译器 C++
C++中的知识点记录
C++中的知识点记录
117 0
ADI
|
缓存 网络协议 算法
[记录]我的日常随笔(一)
[记录]我的日常随笔(一)
ADI
145 0
ADI
|
前端开发 JavaScript
[记录]我的日常随笔(二)
[记录]我的日常随笔(二)
ADI
114 0
|
SQL 关系型数据库 MySQL
牛客网数据库SQL实战详细剖析(51-60)(更新完结)
牛客网数据库SQL实战详细剖析(51-60)(更新完结)
|
前端开发
记录我的第一篇文章
介绍 本人95年处女座一枚 3年小前端 性别:男 爱好:女(哈哈,当然也还有其他爱好) 初心  一直想做自己的博客很久了,但其实这个想法在2016年就已经产生了,奈何一直拖到了现在才终于上线,在读北大青鸟专业之前,最早接触的还是腾讯微博以及QQ空间,这些地方都是用来瞎写一些乱七八糟的东西。
1463 0