简体   繁体   English

在JSON.stringify()中,instanceof的行为有何不同?

[英]What does instanceof behave differently inside JSON.stringify()?

I'm using decimal.js for some financial calculations in Node. 我在Node中使用decimal.js进行一些财务计算。 I'm writing a custom JSON.stringify replacer function , but when I test the property types using instanceof , I get a different result than when I do the same test outside of the replacer function. 我正在编写一个自定义的JSON.stringify替换函数 ,但是当我使用instanceof测试属性类型时,我获得的结果与在replacer函数之外进行相同测试时的结果不同。

Here's a runnable example: 这是一个可运行的例子:

 const myObj = { myNum: new Decimal(0.3) }; // logs 'Property "myNum" is a Decimal: true' console.log('Property "myNum" is a Decimal:', myObj.myNum instanceof Decimal); const replacer = (key, value) => { if (key === 'myNum') { // logs 'Property "myNum" is a Decimal: false' console.log('Property "myNum" is a Decimal:', value instanceof Decimal); } if (value instanceof Decimal) { return value.toNumber() } else { return value; } } JSON.stringify(myObj, replacer, 4); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/decimal.js/10.0.0/decimal.js"></script> 

Why is this happening? 为什么会这样?

If I replace the Decimal instance with an instance of my own custom class, both instanceof tests behave the same, as expected: 如果我用我自己的自定义类的实例替换Decimal实例,则两个instanceof测试的行为与预期的相同:

 function MyClass() {} const myObj = { myClass: new MyClass() }; // logs 'Property "myClass" is a MyClass: true' console.log('Property "myClass" is a MyClass:', myObj.myClass instanceof MyClass); const replacer = (key, value) => { if (key === 'myClass') { // logs 'Property "myClass" is a MyClass: true' console.log('Property "myClass" is a MyClass:', value instanceof MyClass); } return value; } JSON.stringify(myObj, replacer, 4); 

Figured it out. 弄清楚了。 The Decimal instance includes a .toJSON() method. Decimal实例包含.toJSON()方法。 When JSON.stringify encounters an object that defines a toJSON function, it calls it and returns the result as the second parameter in the replacer function instead of the object reference. JSON.stringify遇到定义toJSON函数的对象时,它会调用它并将结果作为replacer函数中的第二个参数而不是对象引用返回。 As a result, the value variable in my example above pointed to a string , not a Decimal instance. 因此,上面示例中的value变量指向一个string ,而不是一个Decimal实例。

From MDN: 来自MDN:

If an object being stringified has a property named toJSON whose value is a function, then the toJSON() method customizes JSON stringification behavior: instead of the object being serialized, the value returned by the toJSON() method when called will be serialized. 如果要进行字符串化的对象具有名为toJSON的属性,其值为函数,则toJSON()方法会自定义JSON字符串化行为:而不是被序列化的对象,调用时toJSON()方法返回的值将被序列化。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON()_behavior https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON()_behavior

To demonstrate this, I can tweak my second example above to include a toJSON function: 为了证明这一点,我可以调整上面的第二个例子来包含一个toJSON函数:

 function MyClass() { // add a toJSON method to my custom class this.toJSON = () => { return 'Hello, world!'; }; }; const myObj = { myClass: new MyClass() }; // logs 'Property "myClass" is a MyClass: true' console.log('Property "myClass" is a MyClass:', myObj.myClass instanceof MyClass); const replacer = (key, value) => { if (key === 'myClass') { // logs 'Property "myClass" is a MyClass: true' console.log('Property "myClass" is a MyClass:', value instanceof MyClass); } return value; } JSON.stringify(myObj, replacer, 4); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM