11

enter image description here

enter image description here

If that is true, why this error happens? The req.body object is not null or undefined as the picture shows.

I use the node-inspector to debug my express.js app, this picture is taken in Chrome Developer Tools.

Express configuration:

app.use(express.bodyParser())

Thanks to your comments, now I found the req.body is undefined, but new question is how to make the toString works again? I want req.body.toString() to return string as below:

enter image description here

How to re-sign a proper toString method?

I tried delete the undefined toString, no good. See:

enter image description here

Yad Smood
  • 2,752
  • 2
  • 24
  • 37
  • 2
    The method may have been removed. Check this out: `var foo = {}; foo.ToString(); foo.toString = undefined; foo.toString();`. Run this and see what happens. – Geeky Guy Sep 05 '13 at 15:51
  • Can you please expand the `__proto__` property(ies) and upload another screenshot? – Bergi Sep 05 '13 at 15:55
  • 1
    Your addendum with `delete` is a bit of a red herring. In your example, `a` never had its own `toString` method; it was always inhered from its prototype. Thus, the `delete` has no effect, because `a` doesn't have a `toString` method (i.e., `a.hasOwnProperty("toString") is false). – apsillers Sep 05 '13 at 15:59
  • I added another picture. – Yad Smood Sep 05 '13 at 15:59
  • What does your Express configuration look like? Some elements like [bodyParser](http://expressjs.com/api.html#bodyParser) will change how `req.body` is handled. – max Sep 05 '13 at 16:04
  • 2
    Turns out the solution is not in the `Object` prototype, but probably lies in a custom `toString` directly on the instance itself. Could you *also* show `req.body.toString` (no parens to invoke it -- I want to see the console rendering of the function's code). – apsillers Sep 05 '13 at 16:06
  • Oh, `req.body.toString` shows `undefined`! So how to re-sign a proper `toString` to it? – Yad Smood Sep 05 '13 at 16:11
  • 1
    If a `toString` value is defined directly on your instance, `delete` is actually the answer here. Your prototype's `toString` function is "shadowed" by another value on the instance itself. By doing `delete req.body.toString` you blow away the `undefined` value and let the prototype's `toString` shine through. You could also do `Object.prototype.toString.call(req.body)` if you wanted to invoke it without `delete`ing the instance `toString`. – apsillers Sep 05 '13 at 16:14
  • @apsillers The `delete` does works, but the `Object.prototype.toString.call(req.body)` works. – Yad Smood Sep 05 '13 at 16:25

1 Answers1

18

Does every object in JS have a toString() method?

No. Only those that inherit it from Object.prototype (as all normal objects do) or define it on its own (or inherit it from their custom prototype) do.

You can create such unusual objects by Object.create(null). You also could give a plain object an own toString property that shadows the inherited one and is not a function (e.g. {toString:0}), but I guess that would've throw a distinct error.

In your case, it seems that the querystring parser used by bodyParser() does (did) indeed create objects without prototypes, to avoid mangling .constructor.prototype when such parameters were used. See qs pullrequest #58 and express issue 1636: Bodyparser not setting object.prototype? (suggesting an update).

How to reassign a proper toString method?

You could just assign any function, like

req.body.toString = function() { return "Hi, I'm a request body"; };

but probably you want the standard one:

req.body.toString = Object.prototype.toString;

Other options would be redefining the prototype via the non-standard __proto__ property (req.body.__proto__ = Object.prototype) or simply applying a standalone function on the object instead of making it a method, like Object.prototype.toString.call(req.body).

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    The results of `toString()` can also vary depending on environment, so even if it's present it's worth keeping in mind that its output may be unreliable for certain functions. – max Sep 05 '13 at 15:56
  • 1
    +1, but note that `req.body` here seems to have an `Object` prototype, so there might be some more going on in the OP's particular case. Maybe this object delegates its `toString` to a non-`Object`-prototyped object? – apsillers Sep 05 '13 at 15:56
  • 1
    @apsillers: Yeah, that's what I suspect as well. Maybe the request body's (custom) `toString` method does try to call `toString()` on some other object… – Bergi Sep 05 '13 at 15:59
  • I added another picture, hope it can help make it more clear. – Yad Smood Sep 05 '13 at 16:01