lodash源码分析-2024.10.12

63 阅读2分钟

defer

// 让一个函数推迟到下次事件循环执行
function defer(func, ...args) {
  if (typeof func !== "function") {
    throw new TypeError("Expected a function");
  }

  // 问:这里为什么是1,不是0?
  // 答: 为了确保必定在下次事件循环执行func
  // 某些js引擎可能会优化timeout为0的情况,让它在本次事件循环末尾执行。以及可能出现多个延迟函数竞争执行问题
  return settimout(func, 1, ...args);
}

// 问:为什么不直接写settimout(func, 1, ...args)?
// 答:封装后的defer除了处理异常传值的情况,还可以让调用更加语义化

delay

function delay(func, wait, ...args) {
  // func必须是函数
  if (typeof func !== "function") {
    throw new TypeError("Expected a function");
  }

  // 把wait转为数字,并设置默认值0
  return settimout(func, +wait || 0, ...args);
}

getTag

// 利用Oject原型上的toString方法获取"类型标签"
const toString = Object.prototype.toString;

function getTag(value) {
  // 问:这里为什么要单独处理null/undefined的情况,直接用下面的toString.call(xxx)不是效率更高吗?
  // 答:在ES5以及之前,某些旧版浏览器对于null/undefined使用toString.call(xxx)可能返回
  // "[object Object]",这就不能正确识别null/undefined的真实“类型标签”了
  // 出于兼容考量,多一些条件判断牺牲一点点性能是值得的
  if (value == null) {
    return value === undefined ? "[object Undefined]" : "[object Null]";
  }

  return toString.call(value);
}

isNil

function isNil(value){
  // null/undefined都是js中的空值,且null == undefined为true
  return value == null;
}

isNull

function isNull(value){
  //直接严格相等就能判断出null
  return value === null;
}

isUndefined

function isUndefined(value){
  //直接严格相等就能判断出undefined
  return value === undefined;
}

isObjectLike

function isObjectLike(value) {
  // 首先排除掉null/undefined,然后typeof出“object”,就可以认为是对象类似物
  return value != null && typeof value === "object";
}

isObject

function isObject(value) {
  // typeof value因为下面需要多次使用,所以定义为一个变量
  const type = typeof value;
  // 首先排除null/undefined,然后type为function/object的就认为是对象
  return value != null && (type === "function" || type === "object");
}