JavaScript 是否可以让数组支持负数索引?

2019-10-03 17:47:16 +08:00
 sdjl

假如我想让数组支持负数索引,实现如下效果

let a = [1,2,3];
console.log(a[-1]); // 3

提示:这样做可能会有问题,例如和其他程序员写的模块冲突,但是我们现在不管这个事情,就是想知道能不能实现。

我目前写了段如下的代码

const pyArray = function(a){
    return new Proxy(a, {
      get: function(target, prop, receiver) {
        let index = Number(prop);
        if (index < 0) {
            prop = String(target.length + index);
        };
        return Reflect.get(target, prop, receiver);
      }
    });
};

let a = [1, 2, 3];
let b = pyArray(a)

console.log(b[-1]); // 3
console.log(a[-1]); // undefined

这里虽然用 Proxy 实现了类似的效果,但是并没有改变原生数组的行为。

能不能改写原生数组的行为,让 a[-1]也能返回 3 ?

6186 次点击
所在节点    程序员
13 条回复
optional
2019-10-03 17:52:23 +08:00
不行
jamesliu96
2019-10-03 18:07:14 +08:00
应该只能用 Proxy
airyland
2019-10-03 18:09:09 +08:00
原生数组的行为是不能变化了,只能对封装对象有效。不过这样的话和直接写工具函数没什么区别了,还不用考虑兼容问题。
https://github.com/sindresorhus/negative-array
love
2019-10-03 20:45:40 +08:00
别在内置对象上加功能是共识。

另外你这个改变也有不兼容风险,毕竟如果有库依赖-1 得到 undefined 的行为呢
xuanbg
2019-10-03 21:01:40 +08:00
这样的需求意义何在?
scnace
2019-10-03 21:06:02 +08:00
这个不符合语义啊
Mutoo
2019-10-03 21:18:03 +08:00
不要太依赖原生的函数,或者是语法糖。
且不说 js 数组的原生函数超级混乱,有时直接修改原数组,有时返回的是浅拷贝。
不如自己实现函数式接口更加方便,简单几行就能实现。

pyGet = (arr, idx) => arr[(idx+arr.length)%arr.length];
pyGet([1,2,3], -1) // 3

柯里化一下就更通用了

pyGet = currying((arr, idx) => arr[(idx+arr.length)%arr.length]);
// or pyGet = arr => idx => arr[(idx+arr.length)%arr.length]);

a = pyGet([1,2,3]);
a(-1); //3

与原生相比,上面的写法不会更费劲。
另外 a = [1,2,3] 本质是 a = new Array(1,2,3); 的语法糖。
这也是为什么 js 没有办法提供[]的代理或重载(语法糖层面)。
shakespaces
2019-10-03 21:54:25 +08:00
还得判断一下负数绝对值大于 length 的时候的问题。。。
starsriver
2019-10-03 21:56:10 +08:00
可以加引号。arr["-b"]

有什么意义吗?
starsriver
2019-10-03 21:58:04 +08:00
我的意思是,做倒序存进去,用索引。
Mutoo
2019-10-04 07:01:12 +08:00
@shakespaces 其实不用,正取溢出 undefined, 负取溢出也应该是 undefined
l1nyanm1ng
2019-10-04 14:53:27 +08:00
arr[arr.length - 1]不就是倒数第一个元素了,同理 arr[arr.length - 2]就是倒数第二个元素了,py 的语法糖不过如此
sdjl
2019-10-04 22:23:59 +08:00
@xuanbg 只是研究一下 JS 语言

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/606164

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX