如何在游戏开发中克隆含内部函数的对象?克隆时函数丢失问题
问题根因
JSON.parse(JSON.stringify(目标对象)) 这类克隆方案的核心流程是将目标对象序列化为符合JSON规范的字符串,再反向解析为新对象。
根据JSON的通用定义,函数、Symbol、循环引用这类结构本身不被JSON序列化支持:当JSON.stringify遍历对象属性遇到函数类型的值时,会直接跳过该属性,不会将其写入最终生成的字符串。这也是你换了多类基于JSON序列化的克隆方案,都出现函数全部丢失结果的根本原因——不是代码实现出错,是这类方案的适用场景本身就不包含带函数的对象克隆。
适配游戏对象克隆的可行方案
结合你“从原型克隆生成带专属方法的游戏对象、存入数组后续调用”的场景,可以根据实际的对象结构选择对应方案:
- 若你的游戏对象的属性均为原始类型(坐标、重量、强度这类数字、布尔值),无嵌套的复杂引用结构,可以直接用对象展开运算符或
Object.assign完成克隆。这类方法会完整复制对象上所有可枚举的自有属性,包括挂载的函数:
运行后得到的新对象会完整保留// 展开运算符实现克隆 objects[1] = { ...objects[0] } // 或者Object.assign实现克隆 objects[1] = Object.assign({}, objects[0])original.e这类函数属性,可直接调用。 - 若你的游戏对象存在嵌套的引用类型属性(比如嵌套子对象、数组),需要完整克隆所有结构同时保留函数,可以手写适配场景的递归克隆逻辑,核心逻辑是遍历每一个属性时,对不同类型的值做差异化处理:
- 对原始类型、函数类型的值,直接赋值/共享引用(函数本身无需逐份拷贝,共享引用即可正常调用,还能降低内存开销)
- 对数组、普通对象类型的值,递归进入结构完成克隆
对应适配你测试用例的简单实现示例:
function deepCloneKeepFunc(source) { // 原始类型、函数类型直接返回值/引用 if (typeof source === 'function' || !(source instanceof Object)) { return source } // 针对数组、普通对象初始化对应结构的新对象 const target = Array.isArray(source) ? [] : {} for (const key in source) { // 只遍历对象自身的属性,避免误拷贝原型链上的内容 if (source.hasOwnProperty(key)) { target[key] = deepCloneKeepFunc(source[key]) } } return target } // 验证你提供的测试用例 var original = {}; original.a = true; original.b = null; original.c = 82; original.d = "a string LOL"; original.e = function() { console.log("everything does not work?"); } original.f = [0, "a", true, false]; const clonedObj = deepCloneKeepFunc(original) console.log(typeof clonedObj.e) // 输出 'function',函数被完整保留 clonedObj.e() // 可正常调用对应方法 - 对游戏项目这类需要大量生成同类型对象的场景,更优的实现方式是将通用的专属方法挂载到对象的原型链上,生成克隆实例时只需要复制每个对象独有的状态属性(坐标、重量、强度这类差异化值),方法通过原型链查找即可。这种方式不需要把同一份函数复制到每个实例上,内存占用更低,也从根源上避免了函数克隆的问题。
内容的提问来源于stack exchange,提问作者Haydan Fisher
相关产品推荐
相关产品推荐

