js手撕

2 阅读1分钟

js手撕

判断循环引用

function detectCircularReference(obj) {
const seen = new WeakSet();

function detect(value) {
// 基本类型不可能有循环引用
if (typeof value !== 'object' || value === null) {
return false;
}

    // 如果对象已经被访问过,说明存在循环引用
    if (seen.has(value)) {
      return true;
    }

    // 记录当前对象已被访问
    seen.add(value);

    // 检查对象的所有属性
    return Object.values(value).some(detect);
}

return detect(obj);
}

// 使用示例
const objA = {};
const objB = { a: objA };
objA.b = objB;

console.log(detectCircularReference(objA)); // 输出: true

解析URL参数

function parseUrl(url) {
  const queryString = url.split("?")[1];
  if (!queryString) return {};

  const keyPairs = queryString.split("&");
  return keyPairs.reduce((params, item) => {
    const [k, v] = item.split("=");
    if (params[k] === undefined) {
      // 参数第一次出现
      params[k] = v;
    } else if (Array.isArray(params[k])) {
      // 参数已经是数组,直接添加新值
      params[k].push(v);
    } else {
      // 参数已经存在但不是数组,转换为数组
      params[k] = [params[k], v];
    }
    return params;
  }, {});
}

深拷贝

function deepClone(obj, map = new WeakMap()) {
  if (obj === null) return null;
  if (typeof obj !== "object") return obj;

  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);

  if (obj instanceof Map)
    return new Map(
      [...obj].map(([key, val]) => [deepClone(key, map), deepClone(val, map)])
    );
  if (obj instanceof Set)
    return new Set([...obj].map((val) => deepClone(val, map)));

  if (map.has(obj)) return map.get(obj); // 处理循环引用
  const newObj = new obj.constructor(); // 先创建新对象
  map.set(obj, newObj); // 然后再将其存储到 map 中

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = deepClone(obj[key], map);
    }
  }
  return newObj;
}