Использование прокси-сервера ES6 приводит к тому, что вызов любой функции не является функцией

Я пытался быть хитрым разработчиком и потерялся в ES6 Proxies. По сути, я хотел захватить любой get или set в свойстве из другого класса, который я написал, и убедиться, что они хранятся где-то еще, помимо объекта. Это выглядит так:

'use strict'
class MyObject()
{
    superAwesomeFunction(){//super awesome code goes here}
}

const myProxyObject = new Proxy(MyObject, {
get: function(target, name, receiver)
{
    if([CONDITIONS THAT MEET MY DEMANDS])
    {
         // deliver property values if they are
         // my super cool database (if they exist)
    }

    // else just ya know, forward it to the actual MyObject
    // property, if it's an actual property on MyObject
    return target[name];
},
set: function(target, name, value)
{
    if([CONDITIONS THAT MEET MY DEMANDS])
    {
         // set property values if they are
         // to super cool database
    }
    else
    {
        // just set the value to the property, which
        // gets created if it doesn't exist (WHICH IS SO COOL)
        target[name] = value;
    }
    return true;
}

Хорошо, что самое интересное в этом? вы можете сделать что-то вроде:

// property that doesn't exist (yet)
console.log(myProxyObject.wholivesinapineappleunderthesea);

// but wait for it...
myProxyObject.wholivesinapineappleunderthesea = 'spongebob';

// bam! now it exists on the object, AND lives in my DB!
console.log(myProxyObject.wholivesinapineappleunderthesea);

Что, несмотря на то, что много работы над чем-то глупым, я не могу объяснить, насколько я счастлив от этого. Однако с этим есть проблема. Помните, что superAwesomeFunction () я вставил в MyObject ()? Что ж, всякий раз, когда я пытаюсь назвать это сейчас, ES6 доставляет мне такую ​​грусть:

myProxyObject.superAwesomeFunction не является функцией

ES6 восседает на троне ЛЖИ! Это полностью верно? Хорошо, я почти уверен, что улавливаю что-то не так, потому что при отладке я вижу, что секция get прокси-сервера фактически принимает вызов superAwesomeFunction (, который имеет смысл как superAwesomeFunction - это свойство, содержащее функцию () {})

ВОПРОС: Кто-нибудь знает какое-нибудь решение, которое позволит мне сохранить мои нелепые свойства на лету и по-прежнему вызывать мою superAwesomeFunction ()? Это ловушка применения?


person Kyle Kinkade    schedule 21.04.2017    source источник
comment
Вам нужно сделать const myProxyObject = new Proxy(new MyObject(), {...}).   -  person idbehold    schedule 21.04.2017


Ответы (3)


Это небольшая синтаксическая ошибка ... вы обертываете прокси-сервер вокруг необработанного класса, а не объекта.

Пытаться:

const myProxyObject = new Proxy(new MyObject(), { ... });

Это должно быть нормально. Например:

> class Blah {
... run() {
..... console.log('yay')
..... }
... }
[Function: blah]
> myProx = new Proxy(new Blah(), {});
blah {}
> myProx.run()
yay
person Sam Redway    schedule 21.04.2017

Чтобы продолжить ответ Сэма.

The following succeeds:

function Foo() {
  this.bar = function() { console.log('baz'); }
}
let foo = new Proxy(new Foo(), {});
foo.bar();

Однако, когда ловушка get добавляется к обработчику, не вызывается функция:

function Foo() {
  this.bar = function() { console.log('baz'); }
}
let foo = new Proxy(new Foo(), {
  get: function(target, prop) {}
});
foo.bar();

Решение здесь состоит в том, чтобы добавить typeof проверку для обработки по умолчанию существующих функций цели:

function Foo() {
  this.bar = function() { console.log('baz'); }
}
let foo = new Proxy(new Foo(), {
  get: function(target, prop) {
    if (typeof target[prop] === 'function') {
      return target[prop].bind(target);
    }
  }
});
foo.bar();

В следующих статьях приведены еще несколько примеров и хороший шаблон для использования с обработчиками прокси: Безопасное расширение объекта набора JavaScript с помощью прокси

person vasilyrud    schedule 17.04.2021

Полный код ответа здесь, всем спасибо!

'use strict'
class MyObject()
{
    superAwesomeFunction(){
        console.log("this works!");
    }
}

const myProxyObject = new Proxy( new MyObject(), {
get: function(target, name, receiver)
{
    if([CONDITIONS THAT MEET MY DEMANDS])
    {
        // do something cool for yourself
    }

    return target[name];
},
set: function(target, name, value)
{
    if([CONDITIONS THAT MEET MY DEMANDS])
    {
        // do something cool for yourself
    }
    else
    {
        // just set the value to the property, which
        // gets created if it doesn't exist (WHICH IS SO COOL)
        target[name] = value;
    }
    return true;
}
});
person Kyle Kinkade    schedule 23.04.2017