const changeKey = (obj, newObj) => {
const keys=Object.keys(obj);
for(let i = 0; i < keys.length; i++) {
const key = keys[i];
newObj[key.replace('_', '')] = obj[key];
if(typeof obj[key] === 'object') {
newObj[key.replace('_', '')] ={};
changeKey(obj[key], newObj[key.replace('_', '')]);
return newObj;
const a = {
a_y: {
a_z: {
y_x: 6
b_c: 1
changeKey(a, {})
function handler(obj) {
function isObject(target) {
if (Array.isArray(target)) return false;
return target !== null && typeof target === "object";
function dfs(obj) {
if (!isObject(obj)) return;
Object.keys(obj).forEach((key) => {
const newKey = key.replaceAll("_", "");
obj[newKey] = obj[key];
delete obj[key];
dfs(obj[newKey]);
dfs(obj);
return obj;
function transformKey(object) {
const array = [object]
while (array.length) {
const obj = array.pop()
for (let key in obj) {
if (Object.prototype.toString.call(obj[key]) === "[object, Object]") {
array.push(obj[key])
obj[key.replace(/_/, "")] = obj[key]
delete obj[key]
return object
function resolve (obj) {
let objStr = JSON.stringify(obj)
let arr = objStr.match(/"\w_\w":/g).map(item => item.replace(/_/g,''))
for(let i of arr){
objStr = objStr.replace(/"\w_\w":/, i)
return JSON.parse(objStr)
console.log(resolve(a))
const keyTransformer = (obj, fn) =>
Object.keys(obj).reduce((acc, current) => {
const key = fn(current);
const val = obj[current];
acc[key] =
val !== null && typeof val === 'object' ? keyTransformer(val, fn) : val;
return acc;
}, {});
const a = {
a_y: {
a_z: {
y_x: 6
b_c: 'asdas_c'
const underscoreKeysObj = keyTransformer(a, key => key.split('_').join(''));
// 如果是对象,推入队列继续
if (typeof item[newKey] === 'object' && item[newKey] !== null) {
queue.unshift(item[newKey]);
return a;
const a = removeUnderScore({
a_y: {
a_z: {
y_x: 6
b_c: 1
console.log(a);
function transfer(obj) {
return JSON.parse(JSON.stringify(obj).replace(/"(\w)_(\w):"/g, '$1$2:'));
想了好长时间用了一个笨办法
const editDeepKey = (obj = {}) => {
const result = {}; // 处理的结果
const shed = []; // 栈信息
let index = 0; // 当前栈索引
// 推进第一级入栈
Object.keys(obj).length && shed.push({
obj: obj,
keys: Object.keys(obj), // 第一级所有的key
convert_key: '', // 转化之后的key
index: 0, // 遍历索引
});
while (shed.length) {
const current = shed[index]; // 当前内容栈
let receive_data = result; // 接收对象
const key = current.keys[current.index]; // 当前遍历原数据的key
let convert_key = ''; // 转化之后的key值
// 如果key不存在说明是上次上级遇到对象进行子级处理,回到上级之后之前是对象的key处于最后一个位置,后面无需在进行处理
// 直接将该栈数据删除出栈即可
if (!key) {
shed.splice(index, 1); // 清空当前栈内存
index--; // 减少栈索引
// 继续下一轮循环
continue;
convert_key = key.replace(/([a-zA-Z])_([a-zA-Z])/g, '$1$2'); // 当前遍历目标数据的key
shed[index].convert_key = convert_key; // 赋值当前遍历目标数据的key
// for循环确定最终的接收对象
for (let i = 0; i < index; i++) {
// 这里不用担心receive_data[shed[i].convert_key]不存在
// 因为在上次检测到父级key对应的值是一个对象的时候就创建对应的对象
// 直接等于该对象
receive_data = receive_data[shed[i].convert_key];
if (Object.prototype.toString.call(current.obj[key]) === '[object Object]') {
// 将当前键的值赋值为一个空对象 这里创建相关对象,涉及到上面for循环里面的直接赋值
receive_data[convert_key] = {}; // 先创建对应键为对象
// 压栈
shed.push({
obj: current.obj[key],
keys: Object.keys(current.obj[key]), // 当前级所有的key
convert_key: '', // 转化之后的key
index: 0, // 遍历索引
});
// 增加栈索引
index++;
// 索引加1
current.index++;
// 继续下一轮循环
continue;
// 非对象值
// 索引加1
current.index++;
receive_data[convert_key] = current.obj[key]; // 赋值
// 本次栈内容全部处理完成 出栈
if (current.index === current.keys.length) {
shed.splice(index, 1); // 清空当前栈内存
index--; // 减少栈索引
return result;
const a = {
a_y: {
a_z: {
y_x: 6
b_c: 1
console.time('time');
console.log(editDeepKey(a));
console.timeEnd('time');