使用getter / setter覆盖javascript属性,同时仍然访问底层属性

时间:2016-02-18 22:31:29

标签: javascript

在构建API polyfill的过程中,我想覆盖具有getter和setter的元素的属性(在本例中为width和height)以捕获对值的更改并在将其传递给底层元素之前对其进行修改。理想情况下,这个过程也是可逆的。这段代码的内容:

var realWidth = null;

function patch(targetObject) {
 realWidth = targetObject.magicalPropertyAccessor("width");
 Object.defineProperty(targetObject, 'width', {
    get: function() {
      return realWidth / 2;
    },
    set: function(value) {
      realWidth = value * 2;
    }
  });
}

function unpatch(targetObject) {
  if (realWidth)
    targetObject.magicalPropertySetter('width', realWidth);
}

示例的意图是,当元素被修补时,它会默默地将对其维度的更改加倍,同时报告原始的未更改的值。如果这是一个函数,它将非常简单,但作为一个属性,不清楚如何缓存对原始访问器的引用。

1 个答案:

答案 0 :(得分:0)

感谢Bergi,我发现Object.getOwnPropertyDescriptor正是我想要的。我曾经尝试过,但错过了我必须去对象的__proto__寻找我正在寻找的房产的财产。 (您的milage可能会因您要替换的属性而异。)这是适用于我的代码:

function WidthPatch(canvas) {
  var self = this;
  var fakeWidth = canvas.width;
  this.canvas = canvas;

  // Cache the real property
  this.realWidthProp = Object.getOwnPropertyDescriptor(canvas.__proto__, 'width');

  // Replace the property with a custom one
  Object.defineProperty(canvas, 'width', {
    configurable: true,
    enumerable: true,
    get: function() {
      return fakeWidth;
    },
    set: function(value) {
      fakeWidth = value;
      // This updates the real canvas property, silently doubling it.
      self.realWidthProp.set.call(canvas, fakeWidth * 2);
    }
  });
}

WidthPatch.prototype.unpatch = function() {
  // Replace the custom property with the original one.
  Object.defineProperty(this.canvas, 'width', this.realWidthProp);
}