繁体   English   中英

访问 JavaScript 对象的默认 getter/setter

[英]Access default getter/setter for JavaScript object

可以使用Object.defineProperty为特定属性覆盖 JavaScript getter 和 setter。 有没有办法访问默认的 getter/setter(即如果 getter/setter 没有被覆盖时使用的函数)? 在我的自定义 setter 中,我希望在某些情况下进行特殊处理,但在其他情况下使用默认处理。 我试过:

Object.defineProperty(obj, 'foo',
  'set': function(val) {
    if (useCustom) {
      doCustomProcessing(obj, 'foo', val);
    }
    else {
      obj['foo'] = val;
    }
  }
);

不幸的是,这会导致堆栈溢出,因为obj['foo'] = val; 导致调用自定义设置器。 所以我想找到一种使用默认设置器设置objfoo属性的方法。 这可能吗?

据我所知,一个属性要么有一个值(数据属性),要么有 getter/setter(访问器属性):它不能同时拥有。 使用闭包下的局部变量或其他属性作为定义了 getter/setter 的属性的底层存储。

例如,

(function() {
    var value;
    Object.defineProperty(obj, 'foo', {
      set: function(val) {
        if (useCustom) {
          value = doCustomProcessing(obj, 'foo', val);
        } else {
          value = val;
        }
      },
      get: function() { return value; }
    });
})();

在 ES6 中,您可以使用Proxy 对象

var myObject = {};

var myProxyObject = new Proxy(myObject, {
  set: function(ob, prop, value) {
    if (prop === 'counter' && value === 10) {
      // Some specialised behaviour
      ob.counter = 0;
    }
    else {
      // Default setter behaviour.
      ob[prop] = value;
    }
    // Return true otherwise you will get a TypeError in strict mode.
    return true;
  }
});

>>> myProxyObject.counter = 5;
>>> console.log(myProxyObject.counter);
5

>>> myProxyObject.counter = 10;
>>> console.log(myProxyObject.counter);
0

我知道如何做到这一点的唯一方法是使变量非私有,但有两个示例,第二个更简洁:

(function testInheritance(global, doc) {
  "use strict";
  var MyFunc = Object.create({}, {
      _foo: {
        value: "Some Default Value",
        writable: true,
        enumerable: true
      },
      foo: {
        get: function() {
          return this._foo;
        },
        set: function(value) {
          this._foo = value;
        }
      }
    }),
    testFunc = Object.create(MyFunc);
  console.log(testFunc.foo); // "Some default value"
  testFunc.foo = "boo";
  console.log(testFunc.foo); // "boo";
 testFunc._foo = "Not a private variable anymore";
 console.log(testFunc.foo); // "Not a private variable anymore"
}(window, document));

(function testInheritanceTwo(global, doc) {
  "use strict";
  var MyFunc = Object.create({}, {
      foo: {
        get: function() {
          if (!this._foo) {
             return "Some default value set by the getter.";
          }
          return this._foo;
        },
        set: function(value) {
          this._foo = value;
        }
      }
    }),
    testFunc = Object.create(MyFunc);
  console.log(testFunc.foo); // "Some default value set by the getter."
  testFunc.foo = "Whomp";
  console.log(testFunc.foo); // "Whomp";
 testFunc._foo = "Not a private variable anymore, unfortunately.";
 console.log(testFunc.foo); // "Not a private variable anymore"
}(window, document));

据我所知:

  1. 您不能使用与您在 set: function(value) 中使用的名称相同的名称来引用值,否则您最终会陷入无限循环,其中设置值调用设置值,然后再次调用自身,依此类推。 因此,你的问题。

  2. 如果您尝试将变量 _foo 设为私有,则 setter 将不起作用。 使用此语法,您似乎可以隐藏变量,但您不能真正将其设为私有。

您可以执行以下操作:

 const counter = new class { count = 1; toString () { return this.count++; } }() console.log(`${counter}`')

 const myString = new class { toString () { return 'This is my string'; } }(); console.log(`${myString}`);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM