JavaScript中类似于Python的__setitem__方法的等效方法是什么?

9
var obj = {}
obj.__setitem__ = function(key, value){
  this[key] = value * value
}
obj.x = 2  // 4
obj.y = 3  // 9

JavaScript 没有 __setitem__,因此这个示例显然不起作用。

在 Python 中,__setitem__ 的工作方式如下:

class CustomDict(dict):
  def __setitem__(self, key, value):
    super(CustomDict, self).__setitem__(key, value * value)

d = CustomDict()
d['x'] = 2  # 4
d['y'] = 3  # 9

在JavaScript中是否可以实现__setitem__行为?所有巧妙的解决方法都将有所帮助。

5个回答

10

能否在JavaScript中实现__setitem__行为?

不行。在 JavaScript 中没有任意属性的 getter/setter。

在 Firefox 中,您可以使用JavaScript 1.5+的getter和setter来定义xy属性,在赋值时对其值进行平方运算,例如:

var obj= {
    _x: 0,
    get x() { return this._x; },
    set x(v) { this._x=v*v; }
};
obj.x= 4;
alert(obj.x);

但是你必须提前声明每个要使用的命名属性的setter。而且它不能跨浏览器工作。


7
不,但是计划支持类似的JavaScript 2功能。在Mozilla bug 312116上提出了以下对象字面量语法建议,看起来它可能是如何实现对象字面量的方式:
({
  get * (property) {
    // handle property gets here
  }
})

我假设集合也会被支持(如set * (property, value) {...})。

看起来不错!你能把建议的页面链接发出来吗? - NVI
@NV:它在bugzilla.mozilla.org上的某个漏洞中。我无法通过一些简单的搜索找到它,所以你可能需要花些时间才能找到它。 - Eli Grey

5
你可以这样做(因为JavaScript中的对象也是关联数组):
var obj = {};
obj._ = function(key, value){
  this[key] = value * value;
}
obj._('x', 2);  // 4
obj._('y', 3);  // 9

alert(obj.x + "," + obj.y); //--> 4,9

1
可以的。但是Python的__setitem__更加优美。 - NVI
1
哦,我明白了讽刺之处。你怎么实现obj.x+=2或类似的操作呢? - NVI

5

在通常实现的Javascript版本中没有真正的setter和getter,因此如果您想模拟效果,必须使用一些不同的语法。对于属性obj.x,使用obj.x()来访问属性的值,obj.x(123)来设置值似乎是一种相当方便的语法。

可以这样实现:

// Basic property class
function Property(value) {
   this.setter(value);
}

Property.prototype.setter = function(value) {
   this.value = value * value;
}

Property.prototype.getter = function() {
   return this.value;
}

Property.prototype.access = function(value) {
   if (value !== undefined)
      this.setter(value);
   return this.getter();
}


// generator function to add convenient access syntax
function make_property(value) {
   var prop = new Property(value);
   function propaccess(value) {
      return prop.access(value);
   }
   return propaccess;
}

现在,由make_property生成的属性支持所需的语法和它们被赋值的方括号值:
var obj = {
   x: make_property(2)
};

alert(obj.x()); // 4
obj.x(3);       // set value
alert(obj.x()); // 9

1

我认为你无法重载当前版本的JavaScript中的[]运算符。在当前的JavaScript中,对象基本上只是关联数组,因此[]运算符只是将键值对添加到作为对象的数组中。

您可以编写方法来设置特定值,甚至可以将一个数字平方并将该值作为键值对添加,但不能通过重载[]运算符来实现。

JavaScript2有一些运算符重载的规范,但该规范已失踪。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接