1. 程式人生 > >獲取函式中某個區域性變數物件種的所有key值?

獲取函式中某個區域性變數物件種的所有key值?

題目

在不改變以下程式碼的情況下,如何獲取函式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獲取到函式內容的字串,然後通過正則去匹配。