admin管理员组

文章数量:1278854

I am trying to call .toString() on a function proxy.

Simply creating a function proxy and calling toString causes "TypeError: Function.prototype.toString is not generic", setting the toString to return the source of the original causes "RangeError: Maximum call stack size exceeded", but creating a get trap for toString works.

Why does simply setting the toString function not work, but making a get trap does?

function wrap(source) {
 return(new Proxy(source, {}))
}
wrap(function() { }).toString()

I am trying to call .toString() on a function proxy.

Simply creating a function proxy and calling toString causes "TypeError: Function.prototype.toString is not generic", setting the toString to return the source of the original causes "RangeError: Maximum call stack size exceeded", but creating a get trap for toString works.

Why does simply setting the toString function not work, but making a get trap does?

function wrap(source) {
 return(new Proxy(source, {}))
}
wrap(function() { }).toString()

function wrap(source) {
 let proxy = new Proxy(source, {})
 proxy.toString = function() {
  return(source.toString())
 }
 return(proxy)
}
wrap(function() { }).toString()

function wrap(source) {
 return(new Proxy(source, {
  get(target, key) {
   if(key == "toString") {
    return(function() {
     return(source.toString())
    })
   } else {
    return(Reflect.get(source, key))
} } })) }
wrap(function() { }).toString()

Share Improve this question asked Jul 8, 2016 at 6:03 Daniel HerrDaniel Herr 20.5k9 gold badges48 silver badges65 bronze badges 2
  • related: esdiscuss/topic/… – tybro0103 Commented Nov 7, 2017 at 22:29
  • Unrelated: return is a keyword, not a function in itself, so it's return x not return(x). The parens doesn't do anything here. – Albin Commented Feb 24, 2018 at 1:34
Add a ment  | 

2 Answers 2

Reset to default 8

I was having the same issue. I finally figured out that it's an issue with this. Add a get trap to your handler, bind the proxied object as this on the proxied property if it's a function, and it seems to work okay:

function wrap(source) {
    return new Proxy(source, {
        get: function (target, name) {
            const property = target[name];
            return (typeof property === 'function') 
                ? property.bind(target)
                : property;
        }
    });
}

console.log(wrap(function () {}).toString());

TypeError: Function.prototype.toString is not generic

Seems like Function.prototype.toString is not supposed to be called on Proxy.

proxy.toString = function() {

This assignment to proxy is passed to the source object as you do not have trap for assignment. If you check source.hasOwnProperty('toString') you'll get true. When you add get trap, you don't change toString method and don't add it into source object, so it works.

The other possible solution is

function wrap(source) {
  let proxy = new Proxy(source, {})
  proxy.toString = Function.prototype.toString.bind(source)
  return proxy
}

本文标签: javascriptFunction Proxy toString() ErrorsStack Overflow