const objectFlat = (obj) => {const res = {};function flat(item, preKey = '') {Object.entries(item).forEach(([key, val]) => {const newKey = preKey ? `${preKey}.${key}` : key;if (val && Object.prototype.toString.call(val) === '[object Object]') {flat(val, newKey);} else {res[newKey] = val;}});}flat(obj);return res;};
Object.create = function (proto) {if (typeof proto !== 'object' && typeof proto !== 'function') {throw new TypeError('Object prototype may only be an Object:' + proto);} else if (proto === null) {throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");}if (typeof properties !== 'undefined') {throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");}// 声明构造函数function Fn() {}// 将构造函数的运行 prototype 连接在指定的 proto 上Fn.prototype = proto;// 返回实例化对象return new Fn();};
function objectFactory(constructor, ...restParams) {// 创建空对象,空对象关联构造函数的原型对象const instance = Object.create(constructor.prototype);// 执行对象类的构造函数,同时该实例的属性和方法被 this 所引用,即 this 指向新构造的实例const result = constructor.call(instance, restParams);// 判断构造函数的运行结果是否对象类型return (typeof result === 'object' && result) || instance;}
function _instanceof(instance, parent) {const constructor = parent.prototype;let proto = Object.getPrototypeOf(instance);while (true) {// 找到了原型链的末端if (proto === null) return false;// 当前实例对象的原型链上找到了当前类if (proto === constructor) return true;proto = Object.getPrototypeOf(proto);}}
function inherit(Child, Parent) {// 以 Parent.protoyep 为原型创建实例let instance = Object.create(Parent.prototype);// 将 instance 的构造函数指定为 Childinstance.constructor = Child;// 将 Child 构造函数的运行指定为 instanceChild.prototype = instance;}
const result = Object.assign({}, source);
const result = { ...source };
问题:原型对象丢失,无法判断实例
能应付日常的拷贝需求,对基本数据类型、对象和数组有效。
const result = JSON.parse(JSON.stringify(source));
const tags = {// 可继续遍历map: '[object Map]',set: '[object Set]',array: '[object Array]',object: '[object Object]',arguments: '[object Arguments]',// 不可继续遍历boolean: '[object Boolean]',number: '[object Number]',string: '[object String]',symbol: '[object Symbol]',error: '[object Error]',date: '[object Date]',regexp: '[object RegExp]',function: '[object Function]',};const deepTags = [tags.map, tags.set, tags.array, tags.object, tags.args];function isObject(val) {const type = typeof val;return val !== null && (type === 'object' || type === 'function');}function cloneSymbol(origin) {return Symbol(origin.description);}function cloneRegExp(origin) {const flag = /\w*$/;const newRegExp = new origin.constructor(origin.source, flag.exec(origin));newRegExp.lastIndex = origin.lastIndex;return newRegExp;}function cloneFunction(origin) {return eval(`(${origin.toString()})`);}function deepClone(origin, hashMap = new WeakMap()) {// 拷贝原始数据类型if (!isObject(origin)) return origin;// 初始化const type = Object.prototype.toString.call(origin);// 初始化拷贝对象let target = null;if (deepTags.includes(type)) {target = new origin.constructor();} else {switch (type) {case tags.boolean:case tags.number:case tags.string:case tags.error:case tags.date:return new origin.constructor(origin);case tags.regexp:return cloneRegExp(origin);case tags.symbol:return cloneSymbol(origin);case tags.function:return cloneFunction(origin);default:return null;}}// 查表,防止循环拷贝if (hashMap.has(origin)) return hashMap.get(origin);// 哈希表设置值hashMap.set(origin, target);// 拷贝 Setif (type === tags.set) {origin.forEach((value) => {target.add(deepClone(value, hashMap));});}// 拷贝 Mapif (type === tags.map) {origin.forEach((value, key) => {target.set(key, deepClone(value, hashMap));});}// 拷贝数组if (type === tags.array) {origin.forEach((item, index) => {target[index] = deepClone(origin[index], hashMap);});}// 拷贝对象if (type === tags.object) {Object.keys(origin).forEach((key) => {target[key] = deepClone(origin[key], hashMap);});}return target;}
参考资料: