Lodash源码阅读-initCloneObject

Lodash 源码阅读-initCloneObject

概述

initCloneObject 是 Lodash 内部用于初始化对象克隆的函数。它负责为即将被克隆的对象创建一个适当的空白对象作为容器,同时确保新创建的对象保持原对象的原型链关系,这是实现深浅克隆的重要基础步骤。

前置学习

依赖函数

  • baseCreate:创建一个继承自指定原型的新对象
  • getPrototype:获取对象的原型
  • isPrototype:检查值是否为原型对象

相关技术知识

  • JavaScript 原型继承机制
  • 构造函数与原型对象的关系
  • Object.create 方法的原理
  • JavaScript 对象创建方式

源码实现

js 复制代码
/**
 * Initializes an object clone.
 *
 * @private
 * @param {Object} object The object to clone.
 * @returns {Object} Returns the initialized clone.
 */
function initCloneObject(object) {
  return typeof object.constructor == "function" && !isPrototype(object)
    ? baseCreate(getPrototype(object))
    : {};
}

实现思路

initCloneObject 函数的实现思路如下:

  1. 判断要克隆的对象是否满足两个条件:
    • 对象的构造函数是一个有效的函数
    • 对象本身不是一个原型对象(通过 isPrototype 检查)
  2. 如果满足条件,调用 baseCreate 创建一个继承自原对象原型的新对象
  3. 如果不满足条件,则简单返回一个空对象 {}

这样设计的目的是为了确保克隆的对象能够保持正确的原型链,同时处理特殊情况(如原型对象本身)。

源码解析

条件判断

js 复制代码
typeof object.constructor == "function" && !isPrototype(object);

这个条件判断包含两部分:

  1. typeof object.constructor == 'function' : 检查对象的构造函数属性是否是一个函数。一般情况下,正常创建的对象都会有一个指向其构造函数的 constructor 属性(通过原型链继承自 Object.prototype)。但在某些情况下,对象可能没有有效的构造函数,比如通过 Object.create(null) 创建的对象。

    示例:

    js 复制代码
    const obj1 = {}; // 标准对象
    console.log(typeof obj1.constructor === "function"); // true, 指向 Object
    
    const obj2 = Object.create(null); // 无原型对象
    console.log(obj2.constructor); // undefined
  2. !isPrototype(object) : 确保对象不是一个原型对象。原型对象(如 Array.prototype)具有特殊性质,直接克隆可能会导致问题。isPrototype 函数的实现如下:

    js 复制代码
    function isPrototype(value) {
      var Ctor = value && value.constructor,
        proto = (typeof Ctor == "function" && Ctor.prototype) || objectProto;
    
      return value === proto;
    }

    它检查一个对象是否就是其构造函数的原型对象。

    示例:

    js 复制代码
    console.log(isPrototype(Array.prototype)); // true
    console.log(isPrototype({})); // false

根据条件创建对象

如果条件满足(对象有有效构造函数且不是原型对象),使用 baseCreate(getPrototype(object)) 创建新对象,否则返回空对象 {}

getPrototype 函数

getPrototype 是获取对象原型的帮助函数,相当于 Object.getPrototypeOf

js 复制代码
var getPrototype = overArg(Object.getPrototypeOf, Object);

这个函数能够获取对象的原型,如 getPrototype({}) 会返回 Object.prototype

总结

initCloneObject 函数展示了 Lodash 在处理对象克隆时的细致考量:

  1. 原型继承 :通过 baseCreategetPrototype 保证克隆对象继承自正确的原型
  2. 特殊情况处理:对原型对象等特殊情况进行单独处理
  3. 兼容性考虑 :内部的 baseCreate 函数提供了对不同环境的兼容性支持

这些考量确保了克隆出的对象不仅有正确的属性值,还保持了正确的原型链关系,这对完整模拟原对象的行为至关重要。

相关推荐
ZHENGZJM14 分钟前
使用JS编写动态表格
开发语言·前端·javascript
喝拿铁写前端17 分钟前
表单设计的哲学:为何我们不再用div堆出区间组件?
前端·架构·代码规范
小彭努力中22 分钟前
153.在 Vue 3 中使用 OpenLayers + Cesium 实现 2D/3D 地图切换效果
前端·javascript·vue.js·3d·ecmascript·echarts
DoraBigHead25 分钟前
原型与原型链 · 千年武学秘籍终解封!
前端·javascript·面试
加油乐1 小时前
vue3实现表格动态列及自定义列排序
前端·vue.js
Hide Asn2 小时前
css-css执行的三种方式和css选择器
前端·css
萌新小白的逆袭2 小时前
HTML的重要知识
前端·html
移动端小伙伴2 小时前
《iOS 通知系统全解》目录索引
前端·swift
罗密欧与猪过夜6762 小时前
React中的State为什么要叫做照片快照
前端
xyccstudio2 小时前
关于 expandSafeArea 不生效问题
前端