I'll answer the bountied sub-question:
I would like to know how to have the new property displayed on the terminal when doing console.log(url) here. I've tried with defineProperty(), writable: true, enumerable: true, etc. to no avail. Should show the properties in Node.js.
After research, I came across this question. Thanks to this method, you can edit the output on node:
let { URL } = require('url');
class MyURL extends URL {
constructor(url, base) {
super(url, base);
this.base = base;
}
[require('util').inspect.custom](){
return `MyURL {base: ${this.base}}`;
}
}
let u = new MyURL('abc.html','http://www.example.com/about')
console.log(u);
This gives, as you can imagine, this output: MyURL {base: http://www.example.com/about}
. However, if I assume well, that's only half the work done, as we don't have all the other properties printed. I am however unable to have a perfect result.
If you don't care about the performances and just want the flat properties, you can use Object.assign
to make a copy of your object without the class:
let { URL } = require('url');
class MyURL extends URL {
constructor(url, base) {
super(url, base);
this.base = base;
}
[require('util').inspect.custom](){
let res = require('util').inspect(Object.assign({}, this));
return `MyURL ${res}`;
}
}
let ur = new MyURL('abc.html','http://www.example.com/about')
console.log(ur);
this gives the following:
MyURL {
base: 'http://www.example.com/about',
[Symbol(context)]: URLContext {
flags: 400,
scheme: 'http:',
username: '',
password: '',
host: 'www.example.com',
port: null,
path: [ 'abc.html' ],
query: null,
fragment: null
},
[Symbol(query)]: URLSearchParams {}
}
You can achieve the same without copying using some dirty trick (I'm not sure if it's a good idea to do this though):
let { URL } = require('url');
class MyURL extends URL {
constructor(url, base) {
super(url, base);
this.base = base;
}
[require('util').inspect.custom](){
this.__proto__ = Object.prototype;
let res = require('util').inspect(this);
this.__proto__ = MyURL.prototype;
return `MyURL ${res}`;
}
}
let ur = new MyURL('abc.html','http://www.example.com/about')
console.log(ur);
But I must admit, it is a bit obscure to me. In case this is not a good solution for you, another possibility is to use a URL
instance for the inspect
call:
let { URL } = require('url');
class MyURL extends URL {
constructor(url, base) {
super(url, base);
this.base = base;
}
[require('util').inspect.custom](){
return `MyURL { base: ${this.base}, super: ${require('util').inspect(new URL(this))} }`;
}
}
let u = new MyURL('abc.html','http://www.example.com/about')
console.log(u);
or the faster and dirtier way:
let { URL } = require('url');
class MyURL extends URL {
constructor(url, base) {
super(url, base);
this.base = base;
}
[require('util').inspect.custom](){
this.__proto__ = URL.prototype;
let res = require('util').inspect(this);
this.__proto__ = MyURL.prototype;
return `MyURL { base: ${this.base}, super: ${res} }`;
}
}
let ur = new MyURL('abc.html','http://www.example.com/about')
console.log(ur);
Giving the output:
MyURL { base: http://www.example.com/about, super: URL {
href: 'http://www.example.com/abc.html',
origin: 'http://www.example.com',
protocol: 'http:',
username: '',
password: '',
host: 'www.example.com',
hostname: 'www.example.com',
port: '',
pathname: '/abc.html',
search: '',
searchParams: URLSearchParams {},
hash: ''
} }
This can be perfected with some string editing.
The last solution I have is to re-create the whole print, by iterating through all the getters of URL
and printing them / adding them to an object to finally print:
let { URL } = require('url');
class MyURL extends URL {
constructor(url, base) {
super(url, base);
this.base = base;
}
[require('util').inspect.custom](){
let res = {};
for (var key in this) {
res[key] = this[key];
}
return `MyURL ${require('util').inspect(res)}`;
}
}
let u = new MyURL('abc.html','http://www.example.com/about')
console.log(u);
this gives:
MyURL {
base: 'http://www.example.com/about',
toString: [Function: toString],
href: 'http://www.example.com/abc.html',
origin: 'http://www.example.com',
protocol: 'http:',
username: '',
password: '',
host: 'www.example.com',
hostname: 'www.example.com',
port: '',
pathname: '/abc.html',
search: '',
searchParams: URLSearchParams {},
hash: '',
toJSON: [Function: toJSON]
}
If you don't care about the MyURL
prefix and prefer to have the coloration, you can simply return res
instead of a string.