最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ES6 proxy work-around for "TypeError: Cannot create proxy with a non-object as target"? - Stack O

programmeradmin1浏览0评论

My last question here: How to store data of a functional chain of Monoidal List?

had many great responses and one of them suggested to implement some sort of type structure in JavaScript:

 const TYPE = Symbol();
  const typeOf = t => x => x == null
    ? x
    : Object.assign(x, {
      [TYPE]: t
    });

  const isType = t => x => x == null
    ? false
    : x[TYPE] === t;

  const Foo = x => typeOf(Foo)(x);

  console.log(
    isType(Foo)(1) // false
    , isType(Foo)([]) // false
    , isType(Foo)({}) // false
    , isType(Foo)(x => x) // false
    , isType(Foo)(true) // false
    , isType(Foo)(undefined) // false
    , isType(Foo)(null) // false
  );
 
  console.log(
    isType(Foo)(Foo(1)) // true
    , isType(Foo)(Foo([])) // true
    , isType(Foo)(Foo({})) // true
    , isType(Foo)(Foo(x => x)) // true
    , isType(Foo)(Foo(true)) // true
    , isType(Foo)(Foo(undefined)) // false
    , isType(Foo)(Foo(null)) // false
  );

  console.log(Foo(1) + Foo(2)); //3
 

My last question here: How to store data of a functional chain of Monoidal List?

had many great responses and one of them suggested to implement some sort of type structure in JavaScript:

 const TYPE = Symbol();
  const typeOf = t => x => x == null
    ? x
    : Object.assign(x, {
      [TYPE]: t
    });

  const isType = t => x => x == null
    ? false
    : x[TYPE] === t;

  const Foo = x => typeOf(Foo)(x);

  console.log(
    isType(Foo)(1) // false
    , isType(Foo)([]) // false
    , isType(Foo)({}) // false
    , isType(Foo)(x => x) // false
    , isType(Foo)(true) // false
    , isType(Foo)(undefined) // false
    , isType(Foo)(null) // false
  );
 
  console.log(
    isType(Foo)(Foo(1)) // true
    , isType(Foo)(Foo([])) // true
    , isType(Foo)(Foo({})) // true
    , isType(Foo)(Foo(x => x)) // true
    , isType(Foo)(Foo(true)) // true
    , isType(Foo)(Foo(undefined)) // false
    , isType(Foo)(Foo(null)) // false
  );

  console.log(Foo(1) + Foo(2)); //3
 

While I thought this is a great idea, another member suggests this is inconsistent since Object.assign is a mutable operation and it should not be allowed in Functional Programming context.

In response, there is another idea to use Proxy instead, so I have tried to implement the similar system by myself.

The result is unfortunately very poor since Proxy seems only to accept Object.

Works as the example

var target = {};
var p = new Proxy(target, {});

p.a = 37; // operation forwarded to the target

console.log(target.a); // 37. The operation has been properly forwarded
 

"Uncaught TypeError: Cannot create proxy with a non-object as target or handler"

var target = 5;
var p = new Proxy(target, {});

p.a = 37; // operation forwarded to the target

console.log(target.a); // 37. The operation has been properly forwarded
 

I also considered to take advantage of Object.create, but does not work in similar manner of Proxy.

Basically, I recognise this is a challenge to implement Inheritance (object-oriented programming) in functional programming with dynamic typing/ duck typing and reflection.

Therefore, I really want to make this implementation work in ES6 Proxy context.

Any great ideas? Thanks.

Share Improve this question edited Jun 21, 2022 at 12:25 Morten 4,6077 gold badges31 silver badges31 bronze badges asked Jul 14, 2018 at 21:29 user6440264user6440264 3
  • 3 I think you have misunderstood what Proxy is. The whole point it to have functions in the second object to handle the "proxying" and of course the first argument has to be an object. Without it it will just pass whatever to the target and it will be mutated just as before. You can pass a new object as the first argument to Object.assign and then it will not mutate the original object. eg. Object.assign({}, x, { [TYPE]: t }). In ES2018 you can do { ...x, [TYPE]: t }. – Sylwester Commented Jul 14, 2018 at 21:58
  • @Sylwester wow, this is not documented at all, and { ...x, ...y} notation works in the current node.js enviroment. Thanks a lot ! – user6440264 Commented Jul 14, 2018 at 22:32
  • @bayesian-study - Seems fairly well-documented to me. In the spec (here, which takes you here, which says "1. If Type(target) is not Object, throw a TypeError exception."), on MDN "target - A target object (can be any sort of object, including a native array, a function or even another proxy) to wrap with Proxy." – T.J. Crowder Commented Jul 15, 2018 at 8:10
Add a ment  | 

1 Answer 1

Reset to default 5

It turns out,

  • Symbol()
  • Object.assign()
  • Proxy

all of them are not necessary to implement Reflection (puter programming) at least for this topic.

See my code below:

const selfAware = i => i[i] = i;
const isAware = i => (i[i] === i);

const I = i => (i === I) || (i == null)
  ? i
  : selfAware(Object(i));

const amI = i => (i === I)
  ? true
  : (i == null)
    ? false
    : isAware(i);

const ss = I(6);

console.log(ss);

console.log(ss[ss]);
//self-similarity
console.log(ss[ss][ss]);


const obj1 = {
  a: 2
};
const obj2 = I(obj1);
console.log(obj1);
console.log(obj2);

console.log(
  I("Hello world!").toString() //Yes, it works!
);

console.log(I(1) + I(2)); //3

console.log(
  (I) //[Function: I]
);
console.log(
  (I)(I) //[Function: I]
);
console.log(
  (I)(I)(I) //[Function: I]
);
console.log(
  (I)(I)(I)(I) //[Function: I]
);
console.log("============================");


console.log(
  amI(I) //true
  , amI(1) // false
  , amI([]) // false
  , amI({}) // false
  , amI(x => x) // false
  , amI(true) // false
  , amI(false) // false
  , amI(undefined) // false
  , amI(null) // false
);

console.log(
  amI(I(I)) // true
  , amI(I(1)) // true
  , amI(I([])) // true
  , amI(I({})) // true
  , amI(I(x => x)) // true
  , amI(I(true)) // true
  , amI(I(false)) // true
  , amI(I(undefined)) // false
  , amI(I(null)) // false
);

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论