是否有一种不那么繁琐的方法来检索原型链中某处的getter和setter方法?

问题描述 投票:2回答:1

我有一个对象的引用,它在原型链的某个地方有一个getter和setter用于某个属性。我想获得对getter和setter方法的引用,以及它们所在的对象。我知道我可以通过手动迭代每个原型对象并检查hasOwnProperty来完成它,如下面的代码片段所示:

const obj2 = (() => {
  const baseProto = {
    get prop() {
      return 'propval';
    },
    set prop(newVal) {
      console.log('setting...');
    }
  };
  const obj1 = Object.create(baseProto);
  return Object.create(obj1);
})();

// From having a reference to obj2, want to get the getter or setter methods,
// and want to get the object they're on, without invoking them:

let currentObj = obj2;
const propToFind = 'prop';
let get, set, foundProto;
while (currentObj) {
  if (currentObj.hasOwnProperty(propToFind)) {
    foundProto = currentObj;
    ({ get, set } = Object.getOwnPropertyDescriptor(currentObj, propToFind));
    break;
  }
  currentObj = Object.getPrototypeOf(currentObj);
}
if (foundProto) {
  console.log('Found:', get, set, foundProto);
}

这看起来相当麻烦,而且while循环很难看。当然,可以使用非常简单的代码调用getter和setter,使用当前对象的调用上下文

obj2.prop = 'newVal';   // invoke setter
const val = obj2.prop;  // invoke getter

但是这会调用函数而不能与它们(或它们所在的原型对象)进行交互。

在上面的片段中,是否有更清晰,更短的方式来实现我正在做的事情?

javascript getter-setter prototypal-inheritance
1个回答
1
投票

这看起来相当麻烦,而且while循环很难看

我不认为这很麻烦,这正是你在原型链上任何地方寻找物业时必须要做的事情。

当然,您不必编写while循环,迭代可以很容易地表示为for循环:

let get, set, foundProto;
for (let currentObj = obj2; currentObj; currentObj = Object.getPrototypeOf(currentObj)) {
  if (currentObj.hasOwnProperty('prop')) {
    foundProto = currentObj;
    ({ get, set } = Object.getOwnPropertyDescriptor(currentObj, 'prop'));
    break;
  }
}
if (foundProto) {
  console.log('Found:', get, set, foundProto);
}

你当然也可以写一个辅助函数来做这个,比如

function getInheritedPropertyDescriptor(obj, prop) {
  for (; obj != null; obj = Object.getPrototypeOf(obj)) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
      return { foundProto: obj, ...Object.getOwnPropertyDescriptor(obj, prop) };
    }
  }
  return null;
}
var result = getInheritedPropertyDescriptor(obj2, 'prop');
if (result) {
  console.log('Found:', result.get, result.set, result.foundProto);
}
© www.soinside.com 2019 - 2024. All rights reserved.