Skip to content

每日学习

JS基础

实现大数相加

js
const addStrings = (num1, num2) => {
  let res = ''
  let i = num1.length - 1
  let j = num2.length - 1
  let flag = 0
  while(i >= 0 || j >= 0) {
    let sum = flag;
    if (i >= 0) sum += parseInt(num1[i--])
    if (j >= 0) sum += parseInt(num2[j--])

    flag = Math.floor(sum / 10)

    res = sum % 10 + res;
  }

  if (flag > 0) {
    res = flag + res;
  }

  return res;
};

console.log(addStrings("456231421242131414212", "45623142124213141421"));
const addStrings = (num1, num2) => {
  let res = ''
  let i = num1.length - 1
  let j = num2.length - 1
  let flag = 0
  while(i >= 0 || j >= 0) {
    let sum = flag;
    if (i >= 0) sum += parseInt(num1[i--])
    if (j >= 0) sum += parseInt(num2[j--])

    flag = Math.floor(sum / 10)

    res = sum % 10 + res;
  }

  if (flag > 0) {
    res = flag + res;
  }

  return res;
};

console.log(addStrings("456231421242131414212", "45623142124213141421"));

实现Promise并发控制

js
async function asyncPool(limit, fns) {
  const res = []
  const exec = []

  for (const item of fns) {
    const p = Promise.resolve().then(() => item())

    res.push(p)

    if (limit <= fns.length) {
      const execute = p.then(() => {
        exec.splice(exec.indexOf(execute), 1)
      })
      exec.push(p)
      console.log(exec.length)
      if (exec.length >= limit) {
        console.log('达到并发数量', limit)
        await Promise.race(exec)
      }
    }
  }

  return Promise.all(res)
}

// 示例测试用例
async function runTest() {
  const taskLimit = 3; // 最大并发数
  const tasks = [
    async () => {
      await sleep(1000); // 模拟异步任务
      console.log('执行完成 1');
      return 1;
    },
    async () => {
      await sleep(1000); // 模拟异步任务
      console.log('执行完成 2');
      return 2;
    },
    async () => {
      await sleep(1000); // 模拟异步任务
      console.log('执行完成 3');
      return 3;
    },
    async () => {
      await sleep(500); // 模拟异步任务
      console.log('执行完成 4');
      return 4;
    },
    async () => {
      await sleep(2000); // 模拟异步任务
      console.log('执行完成 5');
      return 5;
    },
    async () => {
      await sleep(1000); // 模拟异步任务
      console.log('执行完成 6');
      return 6;
    },
    async () => {
      await sleep(3000); // 模拟异步任务
      console.log('执行完成 7');
      return 7;
    },
    async () => {
      await sleep(500); // 模拟异步任务
      console.log('执行完成 8');
      return 8;
    },
  ];

  console.log(`Running asyncPool with a limit of ${taskLimit}`);
  const results = await asyncPool(taskLimit, tasks);
  console.log(`Results: ${results}`);
}

// 辅助函数,模拟异步任务
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

// 运行测试用例
runTest().then(() => {
  console.log('执行完毕');
}).catch(console.error);
async function asyncPool(limit, fns) {
  const res = []
  const exec = []

  for (const item of fns) {
    const p = Promise.resolve().then(() => item())

    res.push(p)

    if (limit <= fns.length) {
      const execute = p.then(() => {
        exec.splice(exec.indexOf(execute), 1)
      })
      exec.push(p)
      console.log(exec.length)
      if (exec.length >= limit) {
        console.log('达到并发数量', limit)
        await Promise.race(exec)
      }
    }
  }

  return Promise.all(res)
}

// 示例测试用例
async function runTest() {
  const taskLimit = 3; // 最大并发数
  const tasks = [
    async () => {
      await sleep(1000); // 模拟异步任务
      console.log('执行完成 1');
      return 1;
    },
    async () => {
      await sleep(1000); // 模拟异步任务
      console.log('执行完成 2');
      return 2;
    },
    async () => {
      await sleep(1000); // 模拟异步任务
      console.log('执行完成 3');
      return 3;
    },
    async () => {
      await sleep(500); // 模拟异步任务
      console.log('执行完成 4');
      return 4;
    },
    async () => {
      await sleep(2000); // 模拟异步任务
      console.log('执行完成 5');
      return 5;
    },
    async () => {
      await sleep(1000); // 模拟异步任务
      console.log('执行完成 6');
      return 6;
    },
    async () => {
      await sleep(3000); // 模拟异步任务
      console.log('执行完成 7');
      return 7;
    },
    async () => {
      await sleep(500); // 模拟异步任务
      console.log('执行完成 8');
      return 8;
    },
  ];

  console.log(`Running asyncPool with a limit of ${taskLimit}`);
  const results = await asyncPool(taskLimit, tasks);
  console.log(`Results: ${results}`);
}

// 辅助函数,模拟异步任务
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

// 运行测试用例
runTest().then(() => {
  console.log('执行完毕');
}).catch(console.error);

实现Promise串行

js
async function serial(...args) {
  return args.reduce((p, item) => p.then(() => item),Promise.resolve())
}
async function serial(...args) {
  return args.reduce((p, item) => p.then(() => item),Promise.resolve())
}

实现Promise常见的方法

js
Promise.resolve = function(value) {
  return new Promise((resolve, reject) => {
    resolve(value)
  })
}

Promise.reject = function(reason) {
  return new Promise((resolve, reject) => {
    reject(reason)
  })
}

Promise.all = function(promises) {
  const result = []
  let count = 0;
  return new Promise((resolve, reject) => {
    for (let i = 0;i < promises.length;i++) {
      promises[i].then((value) => {
        result[i] = value;
        count++
        if (count >= promises.length) {
          resolve(result)
        }
      }, reject);
    }
  })
}

Promise.race = function(promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0;i < promises.length;i++) {
      promises[i].then(resolve, reject)
    }
  })
}

Promise.deferred = function() {
  const def = {}
  def.promise = new Promise((resolve, reject) => {
    def.resolve = resolve
    def.reject = reject
  })
  return def;
}

Promise.allSettled = function(promises) {
  const result = []
  return new Promise((resolve) => {
    for (let i = 0;i < promises.length;i++) {
      promises[i].then((value) => {
        result[i] = {
          status: 'fullfilled',
          value
        }
      }, (reason) => {
        result[i] = {
          status: 'reject',
          reason
        }
      }).finally(() => {
        if (i === promises.length - 1) {
          resolve(result)
        }
      })
    }
  })
}
Promise.resolve = function(value) {
  return new Promise((resolve, reject) => {
    resolve(value)
  })
}

Promise.reject = function(reason) {
  return new Promise((resolve, reject) => {
    reject(reason)
  })
}

Promise.all = function(promises) {
  const result = []
  let count = 0;
  return new Promise((resolve, reject) => {
    for (let i = 0;i < promises.length;i++) {
      promises[i].then((value) => {
        result[i] = value;
        count++
        if (count >= promises.length) {
          resolve(result)
        }
      }, reject);
    }
  })
}

Promise.race = function(promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0;i < promises.length;i++) {
      promises[i].then(resolve, reject)
    }
  })
}

Promise.deferred = function() {
  const def = {}
  def.promise = new Promise((resolve, reject) => {
    def.resolve = resolve
    def.reject = reject
  })
  return def;
}

Promise.allSettled = function(promises) {
  const result = []
  return new Promise((resolve) => {
    for (let i = 0;i < promises.length;i++) {
      promises[i].then((value) => {
        result[i] = {
          status: 'fullfilled',
          value
        }
      }, (reason) => {
        result[i] = {
          status: 'reject',
          reason
        }
      }).finally(() => {
        if (i === promises.length - 1) {
          resolve(result)
        }
      })
    }
  })
}

实现ajax请求

js
const xhr = new XMLHttpRequest()
xhr.open(method, url,true)

xhr.setRequestHeader('Content-Type', 'application/json')

xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    const text = xhr.responseText; // 获取响应内容
  }
}
const xhr = new XMLHttpRequest()
xhr.open(method, url,true)

xhr.setRequestHeader('Content-Type', 'application/json')

xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    const text = xhr.responseText; // 获取响应内容
  }
}

readyState 是 XMLHttpRequest 对象的一个属性,用来标识当前 XMLHttpRequest 对象处于什么状态。 readyState 总共有 5 个状态值,分别为 0~4,每个值代表了不同的含义

0:未初始化 -- 尚未调用.open()方法; 1:启动 -- 已经调用.open()方法,但尚未调用.send()方法; 2:发送 -- 已经调用.send()方法,但尚未接收到响应; 3:接收 -- 已经接收到部分响应数据; 4:完成 -- 已经接收到全部响应数据,而且已经可以在客户端使用了; 编辑此页面

实现apply和call

js
Function.prototype.call = function(context) {
  context.fn = this;
  const arr = []
  for (let i = 1;i < arguments.length;i++) {
    arr.push(`arguments[${i}]`)
  }
  const ret = eval(`context.fn(${arr})`)
  delete context.fn;
  return ret;
}

Function.prototype.apply = function (context, args) {
  var context = context || window;
  context.fn = this;
  var res;
  if (!args) {
    res = context.fn();
  } else {
    const arr = [];
    for (var i = 0; i < args.length; i++) {
      arr.push("args[" + i + "]");
    }
    res = eval("context.fn(" + arr + ")");
  }
  delete context.fn;
  return res;
};
Function.prototype.call = function(context) {
  context.fn = this;
  const arr = []
  for (let i = 1;i < arguments.length;i++) {
    arr.push(`arguments[${i}]`)
  }
  const ret = eval(`context.fn(${arr})`)
  delete context.fn;
  return ret;
}

Function.prototype.apply = function (context, args) {
  var context = context || window;
  context.fn = this;
  var res;
  if (!args) {
    res = context.fn();
  } else {
    const arr = [];
    for (var i = 0; i < args.length; i++) {
      arr.push("args[" + i + "]");
    }
    res = eval("context.fn(" + arr + ")");
  }
  delete context.fn;
  return res;
};

实现 asyncToGenerator

js
function asyncToGenerator(fn) {
  return function() {
    const gen = fn.bind(this, arguments)
    return new Promise((resolve, reject) => {
      function step(key, args) {
        let res
        try {
          res = gen[next](args)
        } catch(e) {
          return reject(e)
        }

        const { value, done } = res;
        if (done) {
          return resolve(value)
        } else {
          return Promise.resolve(value).then(val => {
            step('next', val)
          }).catch((e) => {
            step('throw', e);
          });
        }
      }
      step('next')
    })
  }
}

// 一个简单的 Generator 函数示例
function* exampleGenerator() {
  yield new Promise((resolve) => setTimeout(() => resolve('Hello'), 1000));
  yield new Promise((resolve) => setTimeout(() => resolve('World'), 1000));
}

// 使用 asyncToGenerator 转换 Generator 函数
const asyncFunction = asyncToGenerator(exampleGenerator);

// 使用转换后的 async 函数
asyncFunction()
  .then((result) => console.log(result))
  .catch((error) => console.error(error))
function asyncToGenerator(fn) {
  return function() {
    const gen = fn.bind(this, arguments)
    return new Promise((resolve, reject) => {
      function step(key, args) {
        let res
        try {
          res = gen[next](args)
        } catch(e) {
          return reject(e)
        }

        const { value, done } = res;
        if (done) {
          return resolve(value)
        } else {
          return Promise.resolve(value).then(val => {
            step('next', val)
          }).catch((e) => {
            step('throw', e);
          });
        }
      }
      step('next')
    })
  }
}

// 一个简单的 Generator 函数示例
function* exampleGenerator() {
  yield new Promise((resolve) => setTimeout(() => resolve('Hello'), 1000));
  yield new Promise((resolve) => setTimeout(() => resolve('World'), 1000));
}

// 使用 asyncToGenerator 转换 Generator 函数
const asyncFunction = asyncToGenerator(exampleGenerator);

// 使用转换后的 async 函数
asyncFunction()
  .then((result) => console.log(result))
  .catch((error) => console.error(error))

实现深拷贝

js
function getType(source) {
  return Object.prototype.toString.call(source);
}

function deepCopy(source, memory) {
  const isPrimitive = (value) => {
    return /Number|Boolean|String|Null|Undefined|Symbol|Function/.test(
      Object.prototype.toString.call(value)
    );
  };
  let result;

  memory || (memory = new WeakMap());

  if (isPrimitive(source)) {
    result = source;
  } else if (Array.isArray(source)) {
    result = source.map((value) => deepCopy(value, memory));
  } else if (getType(source) === "[object Date]") {
    result = new Date(source);
  } else if (getType(source) === "[object Regex]") {
    result = new Regex(source);
  } else if (getType(source) === "[object Set]") {
    result = new Set();
    for (const value of source) {
      result.add(deepClone(value, memory));
    }
  } else if (getType(source) === "[object Map]") {
    result = new Map();
    for (const [key, val] of source) {
      result.set(key, deepCopy(val, memory));
    }
  } else {
    if (memory.has(source)) {
      result = memory.get(source);
    } else {
      result = Object.create(null);
      memory.set(source, result);
      Object.keys(source).forEach((key) => {
        const value = source[key];
        result[key] = deepClone(value, memory);
      });
    }
  }
}
function getType(source) {
  return Object.prototype.toString.call(source);
}

function deepCopy(source, memory) {
  const isPrimitive = (value) => {
    return /Number|Boolean|String|Null|Undefined|Symbol|Function/.test(
      Object.prototype.toString.call(value)
    );
  };
  let result;

  memory || (memory = new WeakMap());

  if (isPrimitive(source)) {
    result = source;
  } else if (Array.isArray(source)) {
    result = source.map((value) => deepCopy(value, memory));
  } else if (getType(source) === "[object Date]") {
    result = new Date(source);
  } else if (getType(source) === "[object Regex]") {
    result = new Regex(source);
  } else if (getType(source) === "[object Set]") {
    result = new Set();
    for (const value of source) {
      result.add(deepClone(value, memory));
    }
  } else if (getType(source) === "[object Map]") {
    result = new Map();
    for (const [key, val] of source) {
      result.set(key, deepCopy(val, memory));
    }
  } else {
    if (memory.has(source)) {
      result = memory.get(source);
    } else {
      result = Object.create(null);
      memory.set(source, result);
      Object.keys(source).forEach((key) => {
        const value = source[key];
        result[key] = deepClone(value, memory);
      });
    }
  }
}

0.1+0.2为什么不等于0.3

在javascript中,Number类型使用的是IEEE754标准来表示浮点数,它会使用64位来存储一个浮点数。

而0.1和0.2的二进制是无限循环的,得出来的值也是无限循环,所以不等于0.3

QA: 如何求小数的二进制 0.625 * 2 = 1.25,所以第一位是1。 小数部分变为0.25。 0.25 * 2 = 0.5,所以第二位是0。 小数部分变为0.5。 0.5 * 2 = 1,所以第三位是1

let、var 和 const 的区别

WeakMap和Map的区别

  • WeakMap的key只能是对象
  • WeakMap无法遍历
  • WeakMap没有clear方法
  • WeakMap没有size属性
  • 没有被引用的key,会被垃圾回收

axios如何取消请求

如果该请求已被发出,XMLHttpRequest.abort() 方法将终止该请求。当一个请求被终止,它的 readyState 将被置为 XMLHttpRequest.UNSENT (0),并且请求的 status 置为 0