确定函数访问的对象属性

时间:2016-04-18 14:07:19

标签: javascript

我有一个像这样的任意深度的对象:

var uid = context.getUrlParameter("documentId");
var doc:NotesDocument = database.getDocumentByUNID(uid);

if(doc.getItemValueString("$$disabled") != "true") {
     // want to return the Edit Mode 
     return "Edit Mode "
} else {
     // do nothing
     return false;
}

我调用一个将上面的const objToAccess = { id: 1, name: { first: 'Foo', last: 'Bar' }, address: { street: { name: '987 Walker', roadType: 'Ave' }, zip: '12345' } }; 作为参数的函数。编辑:此功能是一个黑盒子。我不知道它是什么样的,无法编辑它。例如:

objToAccess

调用该函数后,我想知道访问了哪些属性。这里是踢球者:如果访问了嵌套对象,我也希望将所有子项标记为被访问。例如,在运行上面的代码之后,我希望得到如下结果:< / p>

const accessFn = objToAccess => {
  const a = objToAccess.id;
  const b = objToAccess.name.first;
  const c = objToAccess.address;
};

我天真的尝试是创建const propsAccessed = { id: true, name: { first: true, last: false }, address: { street: { name: true, roadType: true }, zip: true } }; 对象&amp;将所有内容设置为false,然后使用getter(下面)。但是,我无法弄清楚如何使用它们,如果只访问父对象,则标记所有子节点。任何想法都会很棒!

propsAccessed

1 个答案:

答案 0 :(得分:2)

我会使用代理:

function isObject(val) {
  return val === Object(val);
}
function detectAccess(obj) {
  if(!isObject(obj)) return {proxy: obj, accessLog: true};
  var subProxies = Object.create(null);
  var accessLog = Object.create(null);
  var proxy = new Proxy(obj, {
    get: function(target, prop, receiver) {
      if(!accessLog[prop]) {
        var recur = detectAccess(obj[prop]);
        accessLog[prop] = recur.accessLog;
        return subProxies[prop] = recur.proxy;
      } else {
        return subProxies[prop];
      }
    }
  });
  return {proxy, accessLog};
}
var {proxy, accessLog} = detectAccess(objToAccess);
accessFn(proxy);
accessLog; // {id:true, name:{first:true}, address:{}}

accessLog告诉我们访问了哪些属性。如果值是基元,则日志将包含true,否则它将包含对象。

然后,如果您想知道例如是否已访问objToAccess.address.street.name,请使用

!!(accessLog.address && accessLog.address.street && accessLog.address.name)

(请参阅test for existence of nested object key以避免重复所有属性路径。)

如果您想要在访问顶层对象的属性时访问所有子树,只需使用

!!(accessLog.address)