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

时间:2018-03-20 11:37:36

标签: javascript json decimal.js

我正在使用decimal.js进行Node中的一些财务计算。我正在编写自定义JSON.stringify replacer function,但是当我使用instanceof测试属性类型时,得到的结果与在replacer函数之外进行相同测试的结果不同。

这是一个可运行的例子:

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>

为什么会这样?

如果我用我自己的自定义类的实例替换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);

1 个答案:

答案 0 :(得分:0)

想出来。 Decimal实例包含.toJSON()方法。当JSON.stringify遇到定义toJSON函数的对象时,它会调用它并将结果作为replacer函数中的第二个参数而不是对象引用返回。因此,上面示例中的value变量指向string,而不是Decimal实例。

来自MDN:

  

如果要进行字符串化的对象具有名为toJSON的属性,其值为函数,则toJSON()方法会自定义JSON字符串化行为:而不是要序列化的对象,{{返回的值} 1}}调用时的方法将被序列化。

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

为了证明这一点,我可以调整上面的第二个例子来包含toJSON()函数:

toJSON