admin管理员组文章数量:1026989
I am trying to create a class that behaves a bit like an array. There are two things that I would like to have:
- has to be iterable
- should allow for property accessing via
[index]
whereindex
is an integer
Making a class iterable is fairly easy:
class MyList {
constructor() {
this._list = [1, 2, 3];
}
[Symbol.iterator]() {
return this._list.values();
}
}
The above allows an instance of the class to be iterated over:
let myList = new MyList();
for (let item of myList) {
console.log(item); // prints out 1, 2, 3
}
Figuring out how to implement the second requirement turns out it's not as easy and the only think I found would be to extend Array
. But this means that I would have to override most of the methods inherited from Array
as I would need those methods to do something else than the built in behaviour.
Is there a way to achieve what I am asking? If so, what would be the best approach to do it?
I am trying to create a class that behaves a bit like an array. There are two things that I would like to have:
- has to be iterable
- should allow for property accessing via
[index]
whereindex
is an integer
Making a class iterable is fairly easy:
class MyList {
constructor() {
this._list = [1, 2, 3];
}
[Symbol.iterator]() {
return this._list.values();
}
}
The above allows an instance of the class to be iterated over:
let myList = new MyList();
for (let item of myList) {
console.log(item); // prints out 1, 2, 3
}
Figuring out how to implement the second requirement turns out it's not as easy and the only think I found would be to extend Array
. But this means that I would have to override most of the methods inherited from Array
as I would need those methods to do something else than the built in behaviour.
Is there a way to achieve what I am asking? If so, what would be the best approach to do it?
Share Improve this question edited Oct 10, 2015 at 16:14 Roland asked Oct 10, 2015 at 16:04 RolandRoland 9,73919 gold badges82 silver badges136 bronze badges 14-
Is it required that a
var test = MyList(); test[2] = 1;
results in a[undefined, undefined, 2]
with atest.length
of3
? Or is it only important, that the data is accessible by[]
? – t.niese Commented Oct 10, 2015 at 16:09 - @t.niese I guess not, I haven't thought about that :) – Roland Commented Oct 10, 2015 at 16:11
-
1
Why do you use
_list
to store the data, instead of storing it directly with the object:this[idx] = 2
instead ofthis._list[idx] = 2
. Is there a reason why you don't want to do that? – t.niese Commented Oct 10, 2015 at 16:15 - @t.niese hmmm, that is actually a good question. It was just an example and it was how I had the implementation before, I stored the values on a private property (I am doing with Typescript, I realize that there are no private properties at this point in JS). But I think it should be fine to store it directly on the class. – Roland Commented Oct 10, 2015 at 16:21
-
1
Sounds like you need a
Proxy
to intercept assignments. – Bergi Commented Oct 11, 2015 at 18:21
1 Answer
Reset to default 8Turns out you can store properties under integer-like string keys, e. g. foo['0'] = 'bar'
and access them with integers, e. g. foo[0] // => bar
. Assigning with an integer also works. Thanks to @JMM for pointing this stuff out.
Thus, the solution is as simple as:
class Foo {
constructor (...args) {
for (let i = 0; i < args.length; i++) {
this[i] = args[i];
}
}
[Symbol.iterator]() {
return Object
.keys(this)
.map(key => this[key])
.values();
}
}
const foo = new Foo('a', 'b', 'c');
for (let item of foo) {
console.log(item); // prints out a, b, c
}
console.log(foo[1]); // prints out b
Demo.
I am trying to create a class that behaves a bit like an array. There are two things that I would like to have:
- has to be iterable
- should allow for property accessing via
[index]
whereindex
is an integer
Making a class iterable is fairly easy:
class MyList {
constructor() {
this._list = [1, 2, 3];
}
[Symbol.iterator]() {
return this._list.values();
}
}
The above allows an instance of the class to be iterated over:
let myList = new MyList();
for (let item of myList) {
console.log(item); // prints out 1, 2, 3
}
Figuring out how to implement the second requirement turns out it's not as easy and the only think I found would be to extend Array
. But this means that I would have to override most of the methods inherited from Array
as I would need those methods to do something else than the built in behaviour.
Is there a way to achieve what I am asking? If so, what would be the best approach to do it?
I am trying to create a class that behaves a bit like an array. There are two things that I would like to have:
- has to be iterable
- should allow for property accessing via
[index]
whereindex
is an integer
Making a class iterable is fairly easy:
class MyList {
constructor() {
this._list = [1, 2, 3];
}
[Symbol.iterator]() {
return this._list.values();
}
}
The above allows an instance of the class to be iterated over:
let myList = new MyList();
for (let item of myList) {
console.log(item); // prints out 1, 2, 3
}
Figuring out how to implement the second requirement turns out it's not as easy and the only think I found would be to extend Array
. But this means that I would have to override most of the methods inherited from Array
as I would need those methods to do something else than the built in behaviour.
Is there a way to achieve what I am asking? If so, what would be the best approach to do it?
Share Improve this question edited Oct 10, 2015 at 16:14 Roland asked Oct 10, 2015 at 16:04 RolandRoland 9,73919 gold badges82 silver badges136 bronze badges 14-
Is it required that a
var test = MyList(); test[2] = 1;
results in a[undefined, undefined, 2]
with atest.length
of3
? Or is it only important, that the data is accessible by[]
? – t.niese Commented Oct 10, 2015 at 16:09 - @t.niese I guess not, I haven't thought about that :) – Roland Commented Oct 10, 2015 at 16:11
-
1
Why do you use
_list
to store the data, instead of storing it directly with the object:this[idx] = 2
instead ofthis._list[idx] = 2
. Is there a reason why you don't want to do that? – t.niese Commented Oct 10, 2015 at 16:15 - @t.niese hmmm, that is actually a good question. It was just an example and it was how I had the implementation before, I stored the values on a private property (I am doing with Typescript, I realize that there are no private properties at this point in JS). But I think it should be fine to store it directly on the class. – Roland Commented Oct 10, 2015 at 16:21
-
1
Sounds like you need a
Proxy
to intercept assignments. – Bergi Commented Oct 11, 2015 at 18:21
1 Answer
Reset to default 8Turns out you can store properties under integer-like string keys, e. g. foo['0'] = 'bar'
and access them with integers, e. g. foo[0] // => bar
. Assigning with an integer also works. Thanks to @JMM for pointing this stuff out.
Thus, the solution is as simple as:
class Foo {
constructor (...args) {
for (let i = 0; i < args.length; i++) {
this[i] = args[i];
}
}
[Symbol.iterator]() {
return Object
.keys(this)
.map(key => this[key])
.values();
}
}
const foo = new Foo('a', 'b', 'c');
for (let item of foo) {
console.log(item); // prints out a, b, c
}
console.log(foo[1]); // prints out b
Demo.
本文标签: javascriptcreate an ES6 class with Array like behaviourStack Overflow
版权声明:本文标题:javascript - create an ES6 class with Array like behaviour - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745651976a2161373.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论