【问题标题】:Extending Array / Proxy in ES6 correctly?在 ES6 中正确扩展数组/代理?
【发布时间】:2018-02-26 09:14:31
【问题描述】:

目前正在尝试对 Array / Object 进行自定义实现(我想最终会非常相似)并且偶然发现了一个让我发疯的问题。

如你所见,b 只是一个 instanceOf 数组,尽管它是从自定义类 CachedArray 创建的,因此我的自定义函数 testPush 没有定义,我无法为了一切找到问题所在。

使用 Nodejs 6

function _setKey(target, key, value) {
  console.log('Setting value', key, 'to', value);
  target[key] = value;
  return true;
}

class ExtendableProxy {
  constructor(a, b) {
    return new Proxy(a, b);
  }
}

class CachedArray extends ExtendableProxy {
  constructor(redis, options) {
    let RawArray = [];

    super(RawArray, {
      set: _setKey
    });

    this._rawArray = RawArray;

    this.redis = redis;
    this.options = options;
  }

  testPush() {
    this.push('Its me');
  }
}

var b = new CachedArray();

console.log('b instanceof CachedArray', b instanceof CachedArray); //false
console.log('b instanceof ExtendableProxy', b instanceof ExtendableProxy); //false
console.log('b instanceof Proxy', b instanceof Proxy); //false
console.log('b instanceof Array', b instanceof Array); //true

b.push('Hello.'); //Works just fine, _setKey is called and executed correctly
b.testPush(); //TypeError: b.testPush is not a function

【问题讨论】:

  • 这不是应该如何创建代理的。代理是对象的包装器,但不是类型。您正在尝试定义一个扩展您的基础对象的类型(在您的情况下为 Array),但代理无法通过扩展原型来工作,因此没有继承链。
  • 我明白了,这可以解释为什么我一开始就不能扩展代理。有没有替代我想要实现的目标?本质上,我需要一个带有我的一些额外功能的数组,但是它有一个连接到它的代理,这样我就可以进一步处理发生在我的类的实例上的任何写入(所以,数组)
  • 仅供参考,这是我尝试使用代理功能扩展数组的尝试,您可以查看here

标签: javascript arrays node.js ecmascript-6


【解决方案1】:

是否有替代我想要实现的目标?本质上我需要一个带有我的一些额外功能的数组,但是它有一个连接到它的代理,这样我就可以进一步处理发生在我的类的实例上的任何写入(所以,数组)

好吧,代理有一个处理程序,它允许您与代理对象进行各种交互。因此,您应该使用它来注入要添加到代理对象的任何其他方法。例如,只需提供get,这样它就会返回一个自定义函数,而不是将调用中继回目标:

function createCachedArray(arr) {
    const customFunctions = {
        testPush() {
            this.push('It’s me');
        },
    };

    return new Proxy(arr, {
        set (target, property, value) {
            console.log(`Setting value ${property} to ${value}`);
            target[property] = value;
            return true;
        },
        has (target, property) {
            return property in customFunctions || property in target;
        },
        get (target, property) {
            if (typeof property === 'string' && property in customFunctions) {
                return customFunctions[property].bind(target);
            }
            else {
                return target[property];
            }
        },
    });
}

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

b.push('foo');
b.testPush();
for (const x of b) {
    console.log(x);
}

【讨论】:

  • 这太天才了!虽然我对它做了一个小改动:在 customFunction 中,我对创建的代理实例本身进行了调用,这样这些调用也会被 setter 回调拦截。我知道这可能会导致无限递归,但我可以忍受 / 将确保它不会发生。非常感谢!
  • 有什么好处或您想解决什么问题?我想念您通过使用代理获得的收益?
  • @jamesemanon 这是一个普遍的问题,代理的用途是什么?或者你是在问这个特定的例子吗?显然,这只是一个展示概念的构造示例。
猜你喜欢
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-07
相关资源
最近更新 更多