JavaScript 数组上的 getter/setter?
有没有办法在数组上获取/设置行为?我想象这样的事情:
var arr = ['one', 'two', 'three'];
var _arr = new Array();
for (var i = 0; i < arr.length; i++) {
arr[i].__defineGetter__('value',
function (index) {
//Do something
return _arr[index];
});
arr[i].__defineSetter__('value',
function (index, val) {
//Do something
_arr[index] = val;
});
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
使用代理,您可以获得所需的行为:
Proxy 构造函数将创建一个包装数组的对象,并使用称为 traps 的函数来覆盖基本行为。
get
函数将被调用以进行任何属性查找,并在返回值之前调用doSomething()
。代理是 ES6 的一项功能,IE11 或更低版本不支持。请参阅浏览器兼容性列表。
Using Proxies, you can get the desired behavior:
The Proxy constructor will create an object wrapping our Array and use functions called traps to override basic behaviors. The
get
function will be called for any property lookup, anddoSomething()
before returning the value.Proxies are an ES6 feature and are not supported in IE11 or lower. See browser compatibility list.
数组访问与普通属性访问没有什么不同。
array[0]
表示array['0']
,因此您可以定义一个名为'0'
的属性并拦截对第一个属性的访问数组项通过它。然而,这确实使得除了短的、或多或少固定长度的数组之外的所有数组都不切实际。您无法一次性为“所有恰好是整数的名称”定义一个属性。
Array access is no different to normal property access.
array[0]
meansarray['0']
, so you can define a property with name'0'
and intercept access to the first array item through that.However, that does make it impractical for all but short, more-or-less-fixed-length Arrays. You can't define a property for “all names that happen to be integers” all in one go.
我查阅了 John Resig 的文章 JavaScript Getters And Setters,但他的原型示例不适合我。在尝试了一些替代方案后,我发现了一种似乎可行的方案。您可以通过以下方式使用 Array.prototype.__defineGetter__:
在 Chrome 和 Firefox 中为我工作。
I looked up in John Resig's article JavaScript Getters And Setters, but his prototype example didn't work for me. After trying out some alternatives, I found one that seemed to work. You can use
Array.prototype.__defineGetter__
in the following way:Worked for me in Chrome and Firefox.
我希望它有帮助。
I hope it helps.
可以为 JavaScript 数组定义 Getters 和 Setters。但你不能同时拥有访问器和值。请参阅 Mozilla 文档:
,因此,如果为数组定义访问器,则需要有第二个数组来存储实际值。以下示例对此进行了说明。
该代码使用三个数组:
带有访问器的数组将返回给调用者。当通过向数组元素分配值来调用
set
时,包含明文值和编码值的数组将被更新。当get
被调用时,它只返回普通值。toString
返回包含编码值的整个查询。但正如其他人已经指出的那样:只有当数组的大小恒定时,这才有意义。您可以修改数组的现有元素,但不能添加其他元素。
It is possible to define Getters and Setters for JavaScript arrays. But you can not have accessors and values at the same time. See the Mozilla documentation:
So if you define accessors for an array you need to have a second array for the actual value. The following example illustrates it.
The code uses three arrays:
The array with the accessors is returned to the caller. When a
set
is called by assigning a value to the array element, the arrays containing the plain and encoded values are updated. Whenget
gets called, it returns just the plain value. AndtoString
returns the whole query containing the encoded values.But as others have stated already: this makes only sense, when the size of the array is constant. You can modify the existing elements of the array but you can not add additional elements.
为什么不为内部对象创建一个新类?
然后,
我想你明白了。
Why not create a new class for the inner objects?
And then,
I think you get the idea.
可以为数组的每个元素创建 setter,但有一个限制:您无法直接为初始化区域之外的索引设置数组元素(例如
myArray[2] = ... // 如果 myArray.length < 2
则不起作用)使用 Array.prototype 函数将起作用。 (例如推、弹出、拼接、移位、取消移位。)我给出了一个如何完成此操作的示例 此处。It is possible to create setters for each element of an array, but there is one limitation: you would not be able to directly set array elements for indexes that are outside the initialized region (e.g.
myArray[2] = ... // wouldn't work if myArray.length < 2
) Using the Array.prototype functions will work. (e.g. push, pop, splice, shift, unshift.) I give an example of how to accomplish this here.这就是我做事的方式。您将必须调整原型创建(我从我的版本中删除了一些)。但这将为您提供我在其他基于类的语言中习惯的默认 getter / setter 行为。
定义 Getter 而没有 Setter 意味着写入元素将被忽略......
希望这会有所帮助。
这给了我预期的行为:
接受德姆瓦尔德曼的批评:现在写作应该是不可能的。
我将代码重写为 1) 不使用废弃的元素 (__ DefineGetter __) 和 2) 不接受对级别元素的任何写入(即:不受控制的写入)。包含一个设置器示例。 (由于降价,我不得不向 __defineGetter 添加间距)
来自 dmvaldmans 的请求:
this is the way I do things. You will have to tweak the Prototype Creation (I removed a bit from my Version). But this will give you the default getter / setter behavior I am used to in other Class-Based Languages.
Defining a Getter and no Setter means that writing to the element will be ignored...
Hope this helps.
This gives me the expected behavior of:
Taking up the critizism from dmvaldman: Writing should now be impossible.
I rewrote the code to 1)not use depracated elements (__ defineGetter __) and 2) not accept any writing (that is: uncontrolled writing) to the levels element. An example setter is included. (I had to add spacing to __ defineGetter because of markdown)
From dmvaldmans request:
这个答案只是基于Proxy的解决方案的扩展。
请参阅使用代理的解决方案,其中只提到了 get,但我们也可以使用
设置为我在这里展示的。
注意:集合中的第三个参数可以携带值...
代码是不言自明的。
This answer is just an extension to the solution based on Proxy.
See the solution with proxy, in that only get is mentioned but we can also use
set as I am showing here.
Notice: 3rd argument in set can carry the value...
The code is self explanatory.
在打字稿中,我做了这种
用法
,这只是想法,您可以添加所需的任何功能。
in typescript i made this
usage
this is just the idea, you can add whatever functionality needed.
正确且现代的方法是 代理 作为接受的答案的数组已经注意到。
话虽这么说,我只发布了下面的替代方案,基于自定义 getter/setter,用于某些向后兼容性的情况并作为概念证明。
The correct and modern way would be to proxy the array as accepted answers have already noted.
That being said, I only post the alternative below, based on custom getters/setters, for some cases of backwards compatibility and as a proof of concept.
您可以将任何您喜欢的方法添加到
Array
中,方法是将它们添加到Array.prototype
中。这是添加 getter 和 setter 的示例You can add whatever methods you like to an
Array
, by adding them toArray.prototype
. Here's an example that adds a getter and setter