$ node
> url = require('url')
{ parse: [Function: urlParse],
resolve: [Function: urlResolve],
resolveObject: [Function: urlResolveObject],
format: [Function: urlFormat],
Url: [Function: Url] }
> var a = url.parse('http://xxx');
undefined
> a
Url {
protocol: 'http:',
slashes: true,
auth: null,
host: 'xxx',
port: null,
hostname: 'xxx',
hash: null,
search: null,
query: null,
pathname: '/',
path: '/',
href: 'http://xxx/' }
> a.toString()
'[object Object]'
Outrageous!
Why isn't url.toString() defined the straight way?
$ node -v
v6.3.1
Yea, this is the correct behavior because the Url
is an object, but we could rewrite Url.prototype.toString
as:
Url.prototype.toString = Url.prototype.format;
Please rewrite it.
[object Object]
is both useless and confusing.
An URL is a string. If I pass around parsed URLs, it is much better if they convert back to a string seamlessly.
Okay, I will submit a pull request tonight, but I'm unsure if this is really necessary in core :)
a
is a URL object. Thus [object Object]
seems correct to me. Maybe you can use a.href
if you want just want a string?
> a.href.toString()
'http://xxx/'
> typeof a.href
'string'
I think rewriting Url.prototype.toString
looks like monkey patching. There is a method url.format()
, toString()
is not a method of Url and I see no reason to create alias by overwriting another method.
see e.g. ECMAScript spec
15.9.5.2 Date.prototype.toString ( )
This function returns a String value. The contents of the String are implementation-dependent, but are
intended to represent the Date in the current time zone in a _convenient, human-readable form._
That is my understanding of the general semantics of the toString()
method.
[object Object]
is clearly useless and thus has no reason to be that way.
Object implements it that way because Object is too abstract, it has no semantics of its own.
URL should have a meaningful toString() implementation.
RegExp (sec 15.10.6.4)
> /abc/.toString()
"/abc/"
> [1,2,3].toString()
"1,2,3"
et cetera
Here is some more:
> new Map().toString()
'[object Map]'
> new Set().toString()
'[object Set]'
> new Promise(() => {}).toString()
'[object Promise]'
If I pass around parsed URLs, it is much better if they convert back to a string seamlessly.
That is why url.parse() and url.format() exist.
Java's Object.toString() grows from the same root:
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString()
Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:getClass().getName() + '@' + Integer.toHexString(hashCode())
Returns:
a string representation of the object.
I see absolutely no point in making toString() intentionally pointless.
There are security implications to consider. If a url.format(url.parse))
round-trip is not 100% lossless, then changing Url#toString()
to Url#format()
may introduce vulnerabilities in applications that accidentally stringify Url objects.
With an explicit format() call, the developer will hopefully at least stop and think.
@bnoordhuis by "lossless", do you mean "side effect free" or something else ?
@gritzko That the result of s == url.format(url.parse(s))
is always true.
@bnoordhuis So, the use of Url objects is essentially discouraged. They should be treated as hashes carrying parsed results.
Well. The API hints at that indeed.
We could maybe do [object Url <href>]
? I think that discourages raw passing but perhaps still is more informative.
What does the WhatWG URL object do here?
The URL
object implements a proper toString()
function:
> var u = new url.URL('http://example.org/foo');
undefined
> u.toString()
'http://example.org/foo'
>
@jasnell's proposal to ECMAScript 馃憤
https://github.com/tc39/proposals/pull/30
To sum it up, the status quo is:
url.format
and url.parse
nowrequire('url').URL
in Node.js v7+I don't see any more we can do now, so closing.
Most helpful comment
The
URL
object implements a propertoString()
function: