[英]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 thetoJSON()
method customizes JSON stringification behavior: instead of the object being serialized, the value returned by thetoJSON()
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.