当属性类型具有自己的'set'时,如何在对象属性上使用'set'?



如果"_position"是Sprite的Point对象成员,具有Number成员x和y,以及它自己的get/set定义,我如何应用更高级别的"set"以使其工作(EDIT:我想达到Sprite中的"set’函数,而不是Point中的"set"函数):

// EDIT: example calling line, embedding context should be unimportant
// 'this' is a Sprite instance
this.position.set(x, y);

Object.defineProperties(Sprite.prototype, {
// a bunch of other properties excised here
    position: {
        get: function() {
            return this._position;
        },
        set: function(_pos) {
            this._position.x = this.transform.x = _pos.x;
            this._position.y = this.transform.y = _pos.y;
            this.transform.updateTransform();
        }
    }
};

目前发生的情况是,"this.position"转到"position.get"属性,然后"this.location.set"转到Point set函数。尝试用自己的get/set"设置"任何对象似乎都会降到最低级别。

感觉必须有办法改变这种行为,但我在谷歌和stackoverflow上的搜索并没有找到答案。很可能我想在这里做什么有一个合适的术语,如果没有这个术语,我就很难正确地表达这个问题。

例如:这很接近,但在我的情况下不太奏效

编辑:我不控制Point的源文件,也不控制this.position.set(x,y)所在的函数;被持有。尽管如果我能证明它不会破坏其他真正想要使用点集函数的对象,我可能能够获得更改调用语法的权限。

由于Bergi没有给出答案,我会的,因为这是一个好问题。

如果你不能控制周围的任何代码,那么,不幸的是,只有丑陋的方法可以做到这一点

A) 按照Bergi的建议,返回一个可以执行任何操作的代理对象。

不利的一面是,周围的代码可能期望它发送的对象与接收的对象匹配。开发人员会比较对象引用而不是值,这样的比较就会失败,这并非不可想象。但这已经在你的代码中发生了,所以如果你已经在使用它,并且没有任何中断,你就可以继续使用了。

此外,如果您采用这种方式,您应该制作MyPoint.prototype = new Point()或其他东西,这样,如果将新方法添加到Point,它们也将在您的类中可用。

B) 为构造函数中的每个对象或您设置它的任何位置手动重写this._position.set和/或setter和getter。这是一个缓慢且极其肮脏的想法,非常糟糕,以至于我写了一个片段,然后删除了它:)

以下是一些关于你实际应该做什么的选项。

A) 同意Sprite的用户使用sprite.position = newPossprite.setPosition(newPos)。然后,您应该在getter中返回_positionObject.freeze()d副本,以确保它没有被不适当地使用。

B) 同意Point的作者在更改时发出一些事件,然后Sprite 可以监听该事件

您不了解Object.defineProperties。别难过,我也没有,直到我进一步研究。您将Object的单个属性的set方法与名为set的属性混淆,后者可能真的有自己的set方法。如果您愿意,可以在属性的value中创建方法。我猜这就是你需要看到的:

Object.defineProperties(Sprite.prototype, {
  set: {
    // can also have get and set here
    value: function(){
      // inside Sprite.prototype.set
    }
  },
  position: {
    get: function() {
      return this._position;
    },
    set: function(_pos) {
      this._position.x = this.transform.x = _pos.x;
      this._position.y = this.transform.y = _pos.y;
      this.transform.updateTransform();
    }
  }
});

我觉得很酷。这种东西一定是在幕后使用的,所以length属性才是真正的方法。

最新更新