在快速'路由处理程序中临时覆盖原型方法是否安全?

时间:2017-04-03 13:59:56

标签: javascript node.js express

我遇到的情况是我有一个包含很多Date个实例的对象。然后将对象转换为JSON,并返回:

router.post('/', function () {
    // Some code that returns the object
    res.status(200).json(object);
});

我需要更改所有Date对象转换为JSON的方式,所以我想这样做:

router.post('/', function() {
    var originalToJSON = Date.prototype.toJSON;
    Date.prototype.toJSON = function() {
        return moment(this).format(...); // some formatting function
    }
    res.status(200).json(object);
    Date.prototype.toJSON = originalToJSON;
});

我意识到这是一种可怕的做法,但我很好奇其含义是什么。由于我在将对象转换为JSON后立即将Date.prototype.toJSON恢复为原始状态,同时res.status(200).json(object)中的请求是否正在运行,并且被覆盖Date.prototype.toJSON

2 个答案:

答案 0 :(得分:3)

代码的某些其他部分将使用更改的JSON方法不应该是一个问题,因为代码运行完成并且不会产生或等待JSON的这两个更改方法,但是你的代码有可能不会使用你改变的方法 - 它实际上取决于res.json()的实现,虽然现在可能有效,但如果Express的内部实现可能会在将来停止工作变化 - 并且依赖它不会改变是一种漏洞抽象,将来会有破损的风险。

你可以在这里做一些其他的事情:

  1. 您可以将自己的自定义对象用于日期,然后根据需要进行转换。
  2. 您可以使用自己的函数来准备JSON,而不是依赖于内置的快速函数
  3. 您可以使用JSON.stringify的replacer参数
  4. 您可以使用整个对象的自定义对象进行标记,而不仅仅是数字1中的日期
  5. 请参阅:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

      

    replacer参数可以是函数,也可以是数组。作为一个函数,它需要两个参数,键和值被字符串化。找到密钥的对象作为replacer的this参数提供。最初使用表示要进行字符串化的对象的空键调用它,然后为要进行字符串化的对象或数组上的每个属性调用它。 [...]如果返回一个String,那么在将该字符串添加到JSON字符串时,该字符串将用作属性的值。

    在您的特定情况下,替换者可以返回您想要格式化的日期,并返回其他所有内容。 JSON.stringify()的replacer参数专门为此类情况创建。

答案 1 :(得分:0)

在这种精确的情况下,一切都是同步的,因此将一次执行。因此,这样做应该是安全的。

但是,弄乱原型通常是一个坏主意,特别是当你的问题有更简单的解决方案时:

function toJSON(input) {
    if(typeof input === 'date') {
        return moment(input).format();
    } else if(typeof input === 'object') {
        let o = {};

        Object.keys(input).map((key) => {
            o[key] = toJSON(input[key]);
        });

        return o;
    } else {
        return input;
    }
}

router.post('/', function() {
    var originalToJSON = Date.prototype.toJSON;
    Date.prototype.toJSON = function() {
        return moment(this).format(...); // some formatting function
    }
    res.status(200).json(toJSON(object));
    Date.prototype.toJSON = originalToJSON;
});