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
函数的实现思路如下:
- 判断要克隆的对象是否满足两个条件:
- 对象的构造函数是一个有效的函数
- 对象本身不是一个原型对象(通过 isPrototype 检查)
- 如果满足条件,调用 baseCreate 创建一个继承自原对象原型的新对象
- 如果不满足条件,则简单返回一个空对象
{}
这样设计的目的是为了确保克隆的对象能够保持正确的原型链,同时处理特殊情况(如原型对象本身)。
源码解析
条件判断
js
typeof object.constructor == "function" && !isPrototype(object);
这个条件判断包含两部分:
-
typeof object.constructor == 'function'
: 检查对象的构造函数属性是否是一个函数。一般情况下,正常创建的对象都会有一个指向其构造函数的 constructor 属性(通过原型链继承自 Object.prototype)。但在某些情况下,对象可能没有有效的构造函数,比如通过Object.create(null)
创建的对象。示例:
jsconst obj1 = {}; // 标准对象 console.log(typeof obj1.constructor === "function"); // true, 指向 Object const obj2 = Object.create(null); // 无原型对象 console.log(obj2.constructor); // undefined
-
!isPrototype(object)
: 确保对象不是一个原型对象。原型对象(如Array.prototype
)具有特殊性质,直接克隆可能会导致问题。isPrototype
函数的实现如下:jsfunction isPrototype(value) { var Ctor = value && value.constructor, proto = (typeof Ctor == "function" && Ctor.prototype) || objectProto; return value === proto; }
它检查一个对象是否就是其构造函数的原型对象。
示例:
jsconsole.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 在处理对象克隆时的细致考量:
- 原型继承 :通过
baseCreate
和getPrototype
保证克隆对象继承自正确的原型 - 特殊情况处理:对原型对象等特殊情况进行单独处理
- 兼容性考虑 :内部的
baseCreate
函数提供了对不同环境的兼容性支持
这些考量确保了克隆出的对象不仅有正确的属性值,还保持了正确的原型链关系,这对完整模拟原对象的行为至关重要。