Skip to content

Latest commit

 

History

History

2692.Make Object Immutable

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

English Version

题目描述

请你编写一个函数,该函数接收一个对象 obj ,并返回该对象的一个新的 不可变 版本。

不可变 对象是指不能被修改的对象,如果试图修改它,则会抛出错误。

此新对象可能产生三种类型的错误消息。

  • 如果试图修改对象的键,则会产生以下错误消息: `Error Modifying: ${key}`
  • 如果试图修改数组的索引,则会产生以下错误消息: `Error Modifying Index: ${index}`
  • 如果试图调用会改变数组的方法,则会产生以下错误消息: `Error Calling Method: ${methodName}` 。你可以假设只有以下方法能够改变数组: ['pop', 'push', 'shift', 'unshift', 'splice', 'sort', 'reverse']

obj 是一个有效的 JSON 对象或数组,也就是说,它是 JSON.parse() 的输出结果。

请注意,应该抛出字符串字面量,而不是 Error 对象。

 

示例 1:

输入:
obj = {
  "x": 5
}
fn = (obj) => { 
  obj.x = 5;
  return obj.x;
}
输出:{"value": null, "error": "Error Modifying: x"}
解释:试图修改对象的键会导致抛出错误。请注意,是否将值设置为与之前相同的值并不重要。

示例 2:

输入: 
obj = [1, 2, 3]
fn = (arr) => { 
  arr[1] = {}; 
  return arr[2]; 
}
输出:{"value": null, "error": "Error Modifying Index: 1"}
解释:试图修改数组会导致抛出错误。

示例 3:

输入:
obj = {
  "arr": [1, 2, 3]
}
fn = (obj) => { 
  obj.arr.push(4);
  return 42;
}
输出:{ "value": null, "error": "Error Calling Method: push"}
解释:调用可能导致修改的方法会导致抛出错误。

示例 4:

输入:
obj = {
  "x": 2,
  "y": 2
}
fn = (obj) => { 
  return Object.keys(obj);
}
输出:{"value": ["x", "y"], "error": null}
解释:没有尝试进行修改,因此函数正常返回。

 

提示:

  • 2 <= JSON.stringify(obj).length <= 105

解法

TypeScript

type Obj = Array<any> | Record<any, any>;

function makeImmutable(obj: Obj): Obj {
    const arrayHandler: ProxyHandler<Array<any>> = {
        set: (_, prop) => {
            throw `Error Modifying Index: ${String(prop)}`;
        },
    };
    const objectHandler: ProxyHandler<Record<any, any>> = {
        set: (_, prop) => {
            throw `Error Modifying: ${String(prop)}`;
        },
    };
    const fnHandler: ProxyHandler<Function> = {
        apply: target => {
            throw `Error Calling Method: ${target.name}`;
        },
    };
    const fn = ['pop', 'push', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
    const dfs = (obj: Obj) => {
        for (const key in obj) {
            if (typeof obj[key] === 'object' && obj[key] !== null) {
                obj[key] = dfs(obj[key]);
            }
        }
        if (Array.isArray(obj)) {
            fn.forEach(f => (obj[f] = new Proxy(obj[f], fnHandler)));
            return new Proxy(obj, arrayHandler);
        }
        return new Proxy(obj, objectHandler);
    };
    return dfs(obj);
}

/**
 * const obj = makeImmutable({x: 5});
 * obj.x = 6; // throws "Error Modifying x"
 */