如何“覆盖”原型上的已定义(get-)属性?

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

我有一些代码在原型上定义了一个getter(但没有setter,如果相关的话)。返回的值在99.99%的情况下是正确的;但是,目标是将属性设置为评估特定对象的不同值。

foo = {}
Object.defineProperty(foo, "bar", {
    // only returns odd die sides
    get: function () { return (Math.random() * 6) | 1; }
});

x = Object.create(foo);
x.bar       // => eg. 5
x.bar = 4   // by fair dice roll
x.bar       // nope => eg. 3

如何为现有对象x重写属性,使其可分配(例如,具有默认属性行为)?

附录:虽然可以在x上定义新属性(值或获取/设置),但我正在寻找是否有办法阻止[原型]中属性的行为并将“条形”转回普通/广告-hoc特定实例的属性。

javascript properties override getter-setter defineproperty
2个回答
9
投票

Object.defineProperty上使用x

var foo = {}
Object.defineProperty(foo, "bar", {
    // only returns odd die sides
    get: function () { return (Math.random() * 6) | 1; }
});

var x = Object.create(foo);
display(x.bar);      // E.g. 5

(function() {
  var bar;
  var proto = Object.getPrototypeOf(x); // Or just use foo

  Object.defineProperty(x, "bar", {
    get: function () { return typeof bar !== "undefined" ? bar : proto.bar; },
    set: function(value) { bar = value; }
  });
})();

display(x.bar);  // Still odd
x.bar = 4;       // By fair dice roll
display(x.bar);  // Shows 4

function display(msg) {
  document.body.insertAdjacentHTML("beforeend", "<p>" + msg + "</p>");
}

我正在寻找是否有办法在[prototype]中停止属性的行为并将“bar”变回普通/ ad-hoc属性。

好的,这有点不同,但仍然使用Object.defineProperty

var foo = {}
Object.defineProperty(foo, "bar", {
    // only returns odd die sides
    get: function () { return (Math.random() * 6) | 1; }
});

var x = Object.create(foo);
display(x.bar);      // E.g. 5

Object.defineProperty(x, "bar", {
  value: undefined,
  writable: true,
  enumerable: true // Or leave off if you want it non-enumerable
});

display(x.bar);  // undefined
x.bar = 4;       // By fair dice roll
display(x.bar);  // Shows 4

function display(msg) {
  document.body.insertAdjacentHTML("beforeend", "<p>" + msg + "</p>");
}

1
投票

作为T.J.克劳德说,再次使用defineProperty就可以了。您可以考虑以下变体,其中setter本身会覆盖该属性:

Foo = function () {}
Foo.prototype = {
  // computes, but only knows odd die sides
  get bar() { 
    console.log("getter invoked")
    return (Math.random() * 6) | 1 
  },
  
  // fix it
  set bar(value) {
    console.log("setter invoked")
    Object.defineProperty(
      this, 'bar', 
      {writable: true, enumerable: true, configurable: true}
    )
    this.bar = value 
  }
}

var x = new Foo
console.log(x.bar)       // => eg. 5
x.bar = 4   // by fair dice roll
console.log(x.bar)       // => 4
x.bar = 2   // no setter, no getter
console.log(x.bar)

我希望你能原谅我用稍微不同的语法重写。它并没有改变任何东西。当我来到这篇文章时,我实际上只是在寻找一种方法来覆盖继承的getter

© www.soinside.com 2019 - 2024. All rights reserved.