问题来源
以前在面试过程中发现一道有趣的题,抖音刷到了袁进老师的视频,对该问题有了更进一步的认识,记录一下。
面试题内容
如何在不改变源代码的情况下,修改 o 对象的属性?
1 2 3 4 5 6 7 8 9 10 11
| let o =(function () { var obj = { a: 1, b: 2, }; return { get: function (key) { return obj[key]; }, }; })()
|
- 首先要读一个对象,就会想到读对象的原型,原型有 valueOf 方法,可以读到对象
1
| console.log(o.get("valueOf"));
|
- 读到 valueOf 方法,可以调用 valueOf 方法,读到对象
1 2 3 4
| console.log(o.get("valueOf")());
let handleValueOf = o.valueOf; handleValueOf();
|
- valueOf 无法读到对象本身,可以直接使用 Object.defineProperty 增加一个返回对象本身的方法
1 2 3 4 5
| Object.defineProperty(Object.prototype, "hack", { get: function () { return this; }, });
|
- 同多原型链自定义方法访问到私有对象本身,更改 o 对象本身,就实现了上述功能
1 2 3 4 5
| let objectBackup = o.get("hack");
objectBackup.c = "hackInner";
console.log(o.get("c"));
|
防御
- 原型设置为 null
1 2 3 4 5 6 7 8 9 10 11 12 13
| let o =(function () { var obj = { a: 1, b: 2, };
Object.setPrototypeOf(obj, null); return { get: function (key) { return obj[key]; }, }; })()
|
- 在访问器中判断是否自身携带属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| let o = (function () { var obj = { a: 1, b: 2, };
return { get: function (key) { if (obj.hasOwnProperty(key)) { return obj[key]; } }, }; })()
|
总结
一切代码皆有漏洞,需要谨慎编写,尽量防御