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

json - Adding "toJSON" method a JavaScript object instance causes Maximum Callstack error - Stack Overflow

programmeradmin2浏览0评论

I wanted to add a .toJson method to an instantiated JavaScript object, which would allow me to get the stringified object instance without functions and prototype, to transmit during a request.

However, it seems like the actual name of the function 'toJSON' as a method name impacts the ability of JavaScript engine (at least in V8) to run the function - that is, if you rename the same exact function to "JSON" instead of "toJSON", it works, however, as "toJSON", it causes a Maximum Callstack error. See example:

function P1(name, age){
    this.name = name;
    this.age= age;
    this.toJSON = function(){
        return JSON.stringify(this);
    }
}

function P2(name, age){
    this.name = name;
    this.age= age;
    this.JSON = function(){
        return JSON.stringify(this);
    }
}

// This causes an error: Uncaught RangeError: Maximum call stack size exceeded(…)
var p1 = new P1('Memory Error', 10);
try {
  p1.toJSON();
} catch(e){
    console.log(e);
}

var p2 = new P2('No Error', 20);
p2.JSON();

Is this an expected behavior of JavaScript? Does it have something to do with "toJSON" being a native method (note: I have verified that on an instantiated object as above, there is no toJSON method on the prototype that would interfere with a redefinition on the instance)? I am trying to determine if I should report this as a bug to V8 team, or this is explainable by someone who knows more about the spec.

Thanks

I wanted to add a .toJson method to an instantiated JavaScript object, which would allow me to get the stringified object instance without functions and prototype, to transmit during a request.

However, it seems like the actual name of the function 'toJSON' as a method name impacts the ability of JavaScript engine (at least in V8) to run the function - that is, if you rename the same exact function to "JSON" instead of "toJSON", it works, however, as "toJSON", it causes a Maximum Callstack error. See example:

function P1(name, age){
    this.name = name;
    this.age= age;
    this.toJSON = function(){
        return JSON.stringify(this);
    }
}

function P2(name, age){
    this.name = name;
    this.age= age;
    this.JSON = function(){
        return JSON.stringify(this);
    }
}

// This causes an error: Uncaught RangeError: Maximum call stack size exceeded(…)
var p1 = new P1('Memory Error', 10);
try {
  p1.toJSON();
} catch(e){
    console.log(e);
}

var p2 = new P2('No Error', 20);
p2.JSON();

Is this an expected behavior of JavaScript? Does it have something to do with "toJSON" being a native method (note: I have verified that on an instantiated object as above, there is no toJSON method on the prototype that would interfere with a redefinition on the instance)? I am trying to determine if I should report this as a bug to V8 team, or this is explainable by someone who knows more about the spec.

Thanks

Share Improve this question asked Sep 29, 2015 at 16:50 netpoeticanetpoetica 3,4254 gold badges29 silver badges37 bronze badges 2
  • 3 JSON.stringify calls the object's toJSON method. This calls JSON.stringify which calls toJSON which calls JSON.stringify... – gen_Eric Commented Sep 29, 2015 at 16:53
  • 4 JSON.stringify() will call the toJSON() function defined on your object. Hopefully you can see why you have the problem... – Jeff Mercado Commented Sep 29, 2015 at 16:53
Add a ment  | 

1 Answer 1

Reset to default 15

This is not what the .toJSON method is used for. You use .toJSON to override the default stringification behavior. The .toJSON is called internally by JSON.stringify, you don't need to call it on your own. .toJSON can return a string, object, array, whatever you want to be stringified in the response from JSON.stringify.

Your .toJSON method needs to do something other than call JSON.stringify(this). Right now you are getting an infinite loop since JSON.stringify(this) calls the object's .toJSON, and so on.

Try something like this:

function P1(name, age){
    this.name = name;
    this.age= age;
    this.toJSON = function(){
        return {
            name: this.name,
            age: this.age
        };
    }
}

var p1 = new P1('Test', 10);
console.log(JSON.stringify(p1));
发布评论

评论列表(0)

  1. 暂无评论