覆盖对象解构默认行为的JavaScript方法

时间:2019-03-27 09:37:08

标签: javascript destructuring

在JS中,有没有一种方法可以消除对象在进行结构分解时的默认行为?

// Normally destructing lifts properties from an object
const foo = {
  a: 1,
  b: 2,
};

const { a, b } = foo; // a = 1, b = 2

// I would like to have a method return the properties to be
// destructured
const bar = {
  toObject: () => {
    return { a, b };
  },
};

const { a, b } = bar; // a = undefiner, b = undefined

我知道我可以简单地使用const { a, b } = bar.toObject();,但这要求对象的使用者知道它的内部工作原理,并且破坏了最少惊讶的原则。

我能想到的最接近的方法是toJSON魔术方法。

3 个答案:

答案 0 :(得分:3)

不。规范requires解析为一个可以通过ToObject转换为对象的值,如果传递了该规范,它仅返回对象本身(即,该对象上没有特殊方法调用以将其转换为其他内容。

enter image description here

答案 1 :(得分:2)

如果要使用数组解构,那会起作用:

 const [a, b] = {
   *[Symbol.iterator]() {
     yield "some"; yield "stuff";
   }
};

答案 2 :(得分:2)

您可以通过使用拦截toObjectownKeys的代理来伪装对象以进行销毁的代理来装饰目标,从而使get正常工作:

let withToObject = obj => new Proxy(obj, {
    ownKeys(o) {
        return Object.keys(o.toObject())
    },
    get(o, prop) {
        return o.toObject()[prop]
    }
});

let bar = withToObject({
    aa: 11,
    bb: 22,
    cc: 33,

    toObject() {
        return {
            a: this.aa,
            b: this.bb
        };
    }
});

const {a, b} = bar;

console.log(a, b)

当然,这不仅影响销毁,还影响与对象的任何其他交互,例如序列化,因此您也必须采取措施使这些工作正常进行。例如,要支持JSON,请像这样修补get

get(o, prop) {
    if (prop === 'toJSON')
        return () => o; // or o.toObject(), whatever fits better
    return o.toObject()[prop]