使用“__proto__”作为对象中的键

use "__proto__" as a key in an Object

我将 myDictionary 声明为一个由用户填充的对象(键/值)
但是对于防御性编程的问题,我想确定如果用户将__proto__作为字典对象的键,值为"some value",he/she将能够使用它,但如您所知,在调用 myDictionary.__proto__ 时将调用对象原型 setter/getter。
我为此找到的一种解决方案是使用 null 作为原型创建对象,因此其原型中不会有 __proto__ setter/getter。但问题是你也不会有其他对象的方法。
我很想看看这里是否有人可以解决这个问题(有什么方法可以在节省性能的同时填充对象方法?)


他们试图将 __proto__ 定义为字典中的关键字。

let myDictionary = {};

let key = prompt("What's the key?", "__proto__");
myDictionary [key] = "some value";

alert(myDictionary [key]); // [object Object], not "some value"!

null为原型创建对象解决问题:

let myDictionary = Object.create(null);

let key = prompt("What's the key?", "__proto__");
myDictionary[key] = "some value";

alert(myDictionary[key]); // "some value"

或者有没有办法用 __proto__ 键分配 属性 而不会弄乱对象原型的 getter/setter ??

您可以使用代理来隐藏对象中不需要的属性。

由于您希望某些属性具有自定义值,因此可以提供这些属性的映射(对象不起作用)。 createObject 函数的 return 将是一个新对象,它检查每个键并根据提供的已定义键映射进行检查。通过这种方式,您基本上可以在对象上拥有自定义属性,而无需牺牲其原型方法,例如 toString().

此行为的实现或使用接受对象上每次查找的 getter 的代理完成,在 getter 内访问的 属性 被拦截,如果它被定义,该值为 returned,否则,正常值为 returned。

function protectedObject(target = {}, definedKeys = new Map()) {   
    const handler = {
        get(target, prop) {
            if (definedKeys.has(prop)) return definedKeys.get(prop);
            return target[prop];
        }
    };
    
    return new Proxy(target, handler);
}

const obj = protectedObject({
  test: 123
}, new Map([
  ["__proto__", "some value"]
]));

console.log(obj.test);
console.log(obj.__proto__);
console.log(obj.toString());

alert(obj[prompt("What's the key?", "__proto__")]);

所有 Object.prototype 方法都完好无损,因为这会创建一个真实的对象(只是代理)。