I know this will work:
function Foo() {};
Foo.prototype.talk = function () {
alert('hello~\n');
};
var a = new Foo;
a.talk(); // 'hello~\n'
But if I want to call
Foo.talk() // this will not work
Foo.prototype.talk() // this works correctly
I find some methods to make Foo.talk
work,
Foo.__proto__ = Foo.prototype
Foo.talk = Foo.prototype.talk
Is there some other ways to do this? I don’t know whether it is right to do so. Do you use class methods or static methods in your JavaScript code?
ES6 supports now
class
&static
keywords like a charm :In your case, if you want to
Foo.talk()
:But it's an inefficient way to implement, using
prototype
is better.Another way, My way is defined as static class:
Above static class doesn't need to use
prototype
because it will be only constructed once as static usage.First off, remember that JavaScript is primarily a prototypal language, rather than a class-based language1.
Foo
isn't a class, it's a function, which is an object. You can instantiate an object from that function using thenew
keyword which will allow you to create something similar to a class in a standard OOP language.I'd suggest ignoring
__proto__
most of the time because it has poor cross browser support, and instead focus on learning about howprototype
works.If you have an instance of an object created from a function2 and you access one of its members (methods, attributes, properties, constants etc) in any way, the access will flow down the prototype hierarchy until it either (a) finds the member, or (b) doesn't find another prototype.
The hierarchy starts on the object that was called, and then searches it's prototype object. If the prototype object has a prototype, it repeats, if no prototype exists,
undefined
is returned.For example:
It looks to me like you've at least somewhat understood these "basic" parts already, but I need to make them explicit just to be sure.
In JavaScript, everything is an object3.
everything is an object.
function Foo(){}
doesn't just define a new function, it defines a new function object that can be accessed usingFoo
.This is why you can access
Foo
's prototype withFoo.prototype
.What you can also do is set more functions on
Foo
:This new function can be accessed using:
I hope by now you're noticing a similarity between functions on a function object and a static method.
Think of
f = new Foo();
as creating a class instance,Foo.prototype.bar = function(){...}
as defining a shared method for the class, andFoo.baz = function(){...}
as defining a public static method for the class.ECMAScript 2015 introduced a variety of syntactic sugar for these sorts of declarations to make them simpler to implement while also being easier to read. The previous example can therefor be written as:
which allows
bar
to be called as:and
baz
to be called as:1:
class
was a "Future Reserved Word" in the ECMAScript 5 specification, but ES6 introduces the ability to define classes using theclass
keyword.2: essentially a class instance created by a constructor, but there are many nuanced differences that I don't want to mislead you
3: primitive values—which include
undefined
,null
, booleans, numbers, and strings—aren't technically objects because they're low-level language implementations. Booleans, numbers, and strings still interact with the prototype chain as though they were objects, so for the purposes of this answer, it's easier to consider them "objects" even though they're not quite.If you have to write static methods in ES5 I found a great tutorial for that:
see @https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/
Just additional notes. Using class ES6, When we create static methods..the Javacsript engine set the descriptor attribute a lil bit different from the old-school "static" method
it sets internal attribute (descriptor property) for brand() to
compared to
that sets internal attribute for brand() to
see that enumerable is set to false for static method in ES6.
it means you cant use the for-in loop to check the object
static method in ES6 is treated like other's class private property (name, length, constructor) except that static method is still writable thus the descriptor writable is set to true
{ writable: true }
. it also means that we can override itWhen i faced such a situation, i have done something like this:
so now i can call the info method as
Logger.info("my Msg", "Tag");