题目
在不改变以下代码的情况下,如何获取函数fn中局部变量obj中所有键值?
function fn (key) {
const obj = { a: 1, b: 2, /* other props */ }
return obj[key];
}
分析
可以看出obj会调用其某个key获取其值,而根据this上下文的原理,如果通过obj调用某个函数,那么this能够直接获取到obj对象,然后就可以通过Object.keys(this)获取到obj的所有键值。
而题目中只是通过key去获取该属性的值,并没有调用什么函数。那么这里就应该想到通过Object.defineProperty劫持obj的某个属性的get,然后return Object.keys(this),如下:
var obj = {a: 1, b: 2};
Object.defineProperty(obj, 'somekey', {
get () { return Object.keys(this) }
});
obj.somekey // ['a', 'b']
但是按照题目的要求,我们能直接劫持obj,那么这里就需要利用到原型链的原理。假定obj上没有'somekey',那么就会在其原型链上查找,即Object.prototype上查找该属性。那么我们可以直接劫持Object.prototype上的'somekey'。
但问题就在于如何保证这个'somekey'在obj上面不存在?— Symbol!
解答
let key = Symbol();
Object.defineProperty(Object.prototype, key, {
get () { return Object.keys(this) }
});
fn(key); // ['a', 'b', /* other props */]
番外篇
当然还有一个骚操作—通过fn.toString获取到函数内容的字符串,然后通过正则去匹配。
本文探讨了在不修改现有代码的基础上,如何巧妙地获取函数内部局部变量中的所有键值。通过利用Symbol和原型链特性,实现了一种创新的解决方案。
1730

被折叠的 条评论
为什么被折叠?



