Duktape/C 数组元素访问器

Duktape/C array element accessors

我正在尝试实现类似于 HTMLCollection 的东西,它是一个数组,可以 lose/gain 没有 JS 操作的元素。

duk_push_object(ctx);
duk_push_string(ctx, "length");
duk_push_c_function(ctx, my_length_getter, 1);
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
duk_push_c_function(ctx, my_item_getter, 1);
duk_put_prop_string(ctx, -2, "item");

像上面那样做我得到一个对象,我可以在上面读取 my_array.length 属性 并通过调用方法 my_array.item(index) 得到一个项目。但是我没有通过使用 my_array[index] 得到一个项目。 如果我将上面的第一行替换为

duk_push_array(ctx);

我收到一条错误消息,指出长度 属性 不可配置。 有没有可能实现我想要的?具有 'lazy' 元素绑定的数组?我的印象是 NetSurf 以某种方式设法做到了这一点,但还没有完全弄清楚如何...

Ecmascript 为 属性 虚拟化提供了两种主要的标准机制:getters/setters(访问器)和 Proxy 对象。 Getters/setters 仅限于您事先明确设置的属性,因此它们并不总是适用于完全虚拟化对象,但 Proxy 对象可以捕获所有 属性 读取和写入等内容。

您应该能够使用代理实施您的用例。 Duktape 实现了 Proxy 陷阱的一个子集(记录在 http://duktape.org/guide.html#es6-proxy 中)。作为捕获所有 属性 读取和写入(但将它们转发到目标)的最小示例:

var target = { foo: 'hello' };
var proxy = new Proxy(target, {
    get: function (targ, key) {
        print('get', key);
        // may also return a virtualized value
        return targ[key];
    },
    set: function (targ, key, val) {
        print('set', key, val);
        // may also capture (virtualize) write, or reject write
        targ[key] = val;
        return true;  // indicate write was allowed
    }
});
print(proxy.foo);
proxy.bar = 123;

运行 "duk" 这会打印:

get foo
hello
set bar 123