In JavaScript If I create a class with a static method and then create a subclass of that class, I can call the static method using subclass name too (static methods are inherited).
Object class which is superclass of all classes has many static methods. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object But why none of those methods can be called using any of subclass names ?
update: I noticed some suggested to explicitly 'extend' Object. But Object class is already superclass of every class in JavaScript. the proof is the .toString() method that every object from every class has it and we know it is inherited from Object class even if you don't explicitly write 'extends Object'. So every class is implicitly extending Object (directly or through inheritance chain) but why non-static methods are being inherited automatically and not the static methods?
as for sample code:
class Test {
constructor() {}
}
const test = new Test();
console.log(test.toString()); // works, inherited from Object class
console.log(Test.<any static method of Object>)); // doesn't work
This was a deliberate decision back in 2012 when ES6 was worked on - you can find it in the meeting notes on Maxmin class semantics:
Mark S. Miller: so
Foo
will inheritObject.create
,Object.getOwnPropertyDescriptor
, etc?Dave Herman: that does mean we'll be more and more hampered from adding methods to Object
[…]
Mark S. Miller: polluting of statics with everything in
Object
is fatal; those are just not relevant to most of the class abstractions people write; when I writeclass Point { }
I don't wantPoint.getOwnPropertyDescriptor
Allen Wirfs-Brock: you only opt into that with
class Point extends Object
; withclass Point { }
you don't get any of that stuff[…]
Yehuda Katz: also, there are override hazards of pollution: if someone freezes
Object
, then you wouldn't be able to override sweet class method names likekeys()
, so the ability to avoid that pollution is important
I'm glad they've chosen this behaviour. Notice that not doing any inheritance of class (constructor function) objects - common in ES5 - was also on the table, it would have meant that calling static methods with dynamic this
on subclasses would have been quite awkward. (Notice that at the time, there was no static
modifier for method definitions, static methods were created by simple Foo.method = function() { … };
assignments).
The "static methods" of Object
were never (and still are not) meant to be dynamic, they neither do use the receiver (this
) nor are they expected to be called on "subclasses". Object
really is just a namespace for the most basic tools (intrinsic functions) for working with objects. When calling Test.create()
, one would expect that to create a new test, not require a prototype object as an argument.
Another reason why this would be weird is that when a class inherits from another class, including Object
, its constructor
must call super()
. Simple classes that don't mean to use any inheritance shouldn't have to deal with that. So the case where a class
has no extends
clause is already handled differently, with a focus on usability since it's the most common use. Not making those class objects inherit from Object
is just another feature.
Finally, it follows the precedent of other built-in "classes". Function.prototype
, Array.prototype
, Error.prototype
etc all inherit from Object.prototype
, but their constructors do not inherit from Object
.
This is also corroborated by early tutorial blog posts such as this one:
[When you] don’t extend:
class Foo {}
- The prototype of
Foo
isFunction.prototype
(as for all functions).- The prototype of
Foo.prototype
isObject.prototype
.That is the same as for functions. Note that the above is not equivalent to
class Foo extends Object
, for the only reason that you normally want to avoidFoo
inheriting methods such asObject.create()
.