how to understand "static" in JavaScript? - javascript

class Foo {
static get bar() {
return 42;
}
get bar() {
return 21;
}
}
I am confused about static get bar() { return 42; },
what's the purpose of this code? who can give me a clear explantion?

static get bar()
is a getter which is not instance specific. It can be used without creating an instance of class Foo as given below:
alert(Foo.bar);
whereas
get bar()
is an object specific getter. It can only be used after creating object of class as given below:
var obj = new Foo();
alert(obj.bar);

static is similar to the static keyword in other programming languages(like java, .net ...etc)
when ever you have static property(method, variable) in your class that has been created only once, and shared across all your class objects instances.
For example if you want to have total users count inside of your class you can do that by using static keyword
Example:
class User {
Constructor() {
}
set name(name) {
this.name = name;
}
get name() {
return this.name;
}
static userCount;
}
when ever you create new user instances you can increment your users count.any of your users can access the userCount variable.To access static variable you cannot use this keyword.because it does not belongs to any instances.so to access static keyword use the following
User.userCount = 0;

Related

Are classes necessary in Javascript? What effect do they have on creating objects?

Consider this example code:
class Test {
say() {
console.log("I'm a test.");
}
}
let TestFromClass = new Test();
let TestFromObject = {
say() {
console.log("I'm also a test.");
}
};
TestFromClass.say(); // Output: I'm a test.
TestFromObject.say(); // Output: I'm also a test.
I understand that it's possible to create objects, such as TestFromObject, without first creating a class with the class keyword. Is class necessary at all? Is there a difference between these two kinds of objects? If so, what effect does it have to use class explicitly?
Using new creates a new object whose internal prototype is the class's prototype. For example:
class Test {
say() {
console.log("I'm a test.");
}
}
let TestFromClass = new Test();
console.log(Object.getPrototypeOf(TestFromClass) === Test.prototype);
This is useful for creating multiple objects. The usual reason to do this is so that each object can have some sort of associated state - generally, the values of its properties. For example, a Person object might have a name and an age property.
However, if there is no data to associate with an instance (as with TestFromClass in the original code), there's not much point having an instance at all. The TestFromObject approach makes much more sense if the purpose is just to collect named functions into a data structure.
That said, it's sometimes desirable to have a class that has some functions associated with it (like say) which don't have anything to do with an instance of its data, while still being able to create an instance - perhaps using other methods on the prototype. This isn't that uncommon, and is done by making the non-instance-related functions static:
class Person {
static canEat() {
return ['apples', 'bananas', 'carrots'];
}
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const p = new Person('Bob', 99);
console.log(p.name);
console.log(Person.canEat());
A class is more or less just syntactic sugar for a prototype:
// The class way
class Test {
say() {
console.log("I'm a test.");
}
}
// The old fashioned way
function Test() {
}
Test.prototype.say = function () {
console.log("I'm a test.");
};
The difference in both these cases with direct object creation is that the methods belong to the prototype, not directly to the object.
The code TestFromClass.say() must go through the prototype chain to find a say method, while TestFromObject directly has the method.
Other than that, there's no difference.
Is there a difference between these two kinds of objects? If so, what effect does it have to use class explicitly?
There effectively isn't a meaningful difference, but it does have some minor effects:
When you create an object with literal syntax, unless you use the special __proto__ property name, its prototype will always be Object.prototype. (Note that __proto__ is officially optional, a JavaScript engine doesn't have to provide it.) When you create it with new X, provided X is a constructor function created with class syntax, the result will have the prototype X.prototype.
Methods defined within an object literal are directly placed on the object. Methods within class X go on X.prototype (non-static ones) which the object inherits.
Objects come in two forms: the declarative (literal) form, and the constructed form.
The literal syntax for an object looks like this:
var myObj = {
key: value
// ...
};
The constructed form looks like this:
var myObj = new Object();
myObj.key = value;
The constructed form and the literal form result in exactly the same sort of object. The only difference really is that you can add one or more key/value pairs to the literal declaration, whereas with constructed-form objects, you must add the properties one-by-one.
Note: It's extremely uncommon to use the "constructed form" for creating objects as just shown. You would pretty much always want to use the literal syntax form. The same will be true of most of the built-in objects.
P.S. To read more in detail go to
https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/this-object-prototypes/ch3.md
So you created a class called Test which is the base class. The you added a method called say() {}.
class Test {
say() {
console.log("I'm a test.");
}
}
Then you created an instance of the Test class below:
let TestFromClass = new Test();
And below that you created a plain JavaScript object called TestFromObject:
let TestFromObject = {
say() {
console.log("I'm also a test.");
}
};
And yes, they will both print out the output you have to their methods:
TestFromClass.say(); // Output: I'm a test.
TestFromObject.say(); // Output: I'm also a test.
The difference will not begin until you utilize the full power of the class you created, for example, utilizing the cconstructor() function like so:
class Test {
constructor() {
}
say() {
console.log("I'm a test.");
}
}
Now the constructor function is automatically called for us when we use the new keyword for the class name. With a constructor function you know also have access to this like so:
class Test {
constructor() {
this.type = 'test';
}
say() {
console.log("I'm a test.");
}
}
Which allows you to do this:
TestFromClass.say(); // Output: I'm a test.
TestFromObject.say(); // Output: I'm also a test.
TestFromClass.type; // Output: test
The constructor is traditionally used to do some initial setup inside the class or particular instance of the class.
The constructor is commonly used by using some arguments when creating a new instance of the class. Maybe you want to specify that the class of Test you have created has 50 questions. You can pass in an object to the new Test instance like so:
let TestFromClass = new Test({ questions: 50 });
You can call this object whatever you want, let's just call the object examination and you can set the number of questions to this examination object.
So now you pass that object into the constructor function and calling that object, examination like so:
class Test {
constructor(examination) {
this.questions = examination.questions;
this.type = 'test';
}
say() {
console.log("I'm a test.");
}
}
let TestFromClass = new Test({ questions: 50 });
TestFromClass.say(); // Output: I'm a test.
TestFromClass.type; // Output: test
TestFromClass.questions; // 50
The other thing you can do with a class object is create a subclass that would extend the functionality of your base class and then you can also add some customized functionality to it.
class Test {
constructor(examination) {
this.questions = examination.questions;
this.type = 'test';
}
say() {
console.log("I'm a test.");
}
}
class Quiz extends Test {
}
So now your Quiz is inheriting all the methods, functions, properties, etcetera that are in the Test class and define additional methods inside of it.
class Test {
constructor(examination) {
this.questions = examination.questions;
this.type = 'test';
}
say() {
console.log("I'm a test.");
}
}
class Quiz extends Test {
constructor(examination) {
this.topic = examination.topic;
}
}
So now to ensure that the constructor function from the parent class is called as well, I can use the super() keyword into the constructor:
class Test {
constructor(examination) {
this.questions = examination.questions;
this.type = 'test';
}
say() {
console.log("I'm a test.");
}
}
class Quiz extends Test {
constructor(examination) {
super(examination)
this.topic = examination.topic;
}
}
Then you can instantiate that subclass like so:
const javascript = new Quiz({topic: 'javascript', questions: 50 });
and finally print it out:
javascript.questions; // Output: 50

How to access the class itself from within a class without using its name [duplicate]

This question already has answers here:
JS call static method from class
(7 answers)
Closed 4 years ago.
Is it possible to access the class itself inside of a classes function:
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(MyClass.myFunction); // "foo" -- it works when using its name. This is what we want but without using the name
console.log(this.myFunction); //undefined
console.log(this.prototype.myFunction); //Cannot read property 'myFunction' of undefined
}
}
new MyClass();
Is it possible to achieve the same as you do with MyClass.myFunction() and access the static methods without using the name of the class (in this case without using MyClass in this example?
Something like this.master.myFunction() (I’m just making master up here it’s obviously not called master)
JSBin: https://jsbin.com/hawituxosu/1/edit?js,console
Is that even possible? Thank you!
you can use constructor for this
Returns a reference to the Object constructor function that created the instance object
The constructor property has three purposes:
1. Get the class object.
2. Create an new instance
3. Invoke super constructor
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(this.constructor.myFunction);
}
}
new MyClass();
an option you can do here is to call static method inside an instance method and call that instance method
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(MyClass.myFunction); // "foo" -- whith using its name it works. This is what we want but without using the name
console.log(this.constructor.myFunction);
}
myFunction2() {
return this.constructor.myFunction();
}
}
const master = new MyClass();
master.myFunction2();
this.constructor.myFoo
The constructor property helps you here
You could work around getting to the class name using:
this.__proto__.constructor.name // MyClass
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(eval(this.__proto__.constructor.name + ".myFunction")); //foo
}
}
new MyClass();

Access class scope within static function ES6

How does one access this scope with a static function of a class? Am I missing something here?
class Example {
constructor() {
this.name = 'Johan';
}
static hello(){
// How to access `this` scope here in the static
Example.name; // Undefined
this.name; // Undefined
}
}
The commenters are correct, this in the context of a static class method is the class itself.
When you create an instance of the class using new, that instance is its own this. You can access properties and methods on the instance through this.
See the examples below:
class Example {
constructor() {
this.name = 'Johan';
}
static hello(){
console.log(this);
console.log(this.name);
}
}
Example.hello(); // logs out the above class definition, followed by the name of the class itself.
let x = new Example();
console.log(x.name); // logs out 'Johan'.
x.hello(); // x does not have `hello()`. Only Example does.

js class static method refer to self (like self in php)

Is there a way to refer to the class that a static method is included in without explicitly specifiying the class again. So instead of this:
class User {
static welcome = 'Hello'
static greet() {
console.log(User.welcome)
}
}
Something like this:
class User {
static welcome = 'Hello'
static greet() {
console.log(self.welcome)
}
}
A class is nothing but a function object. Static methods are nothing but function properties on that object. Whenever you call obj.method(), this refers to the object inside that function.
So if you call the method with User.greet(), this will refer to the function object User.
class User {
static get welcome() {
return 'hello';
}
static greet() {
console.log(this.welcome)
}
}
User.greet();
Inside instance methods you can refer to the class via this.constructor.
You can allways use "this":
class User {
static welcome = 'Hello';
static greet() {
alert(this.welcome)
}
}
User.greet();
But in case of static methods it will refer to type itself.
Here is what specs says about value of "this":
When the root declaration is an instance member or constructor of a
class, the ThisType references the this-type of that class.
When the root declaration is a member of an interface type, the
ThisType references the this-type of that interface.
Sadly, there is no such thing as self in JS, since this in JS is basically already a "merge" of this and self as described in other answers.
If you don't like to do this for a static call, you can actually do pretty similar thing as in PHP.
TL;DR Refer to the class by its name e.g. MyClass.myMethod()
class A {
static one () { console.log("I am one"); }
static two () { A.one(); }
}
A.one(); // Outputs/Logs: "I am one"
PHP equivalent could be something like
<?php
class A {
public static function one() { echo "I am one"; }
public static function two() { A::one(); }
}
A::two(); // Outputs: "I am one"
Bonus info: In JS, you can even do static two = () => A.one();, which is not available with arrow functions in PHP since in class static variable implies constant expression.

creating a public method on a constructor function: Why use the prototype keyword?

If I create a constructor function BlahWidget and give it 2 public methods: publicHello and secondHello. I assign publicHello directly inside the widget using 'this' but use the prototype object to assign the secondHello method, what difference does that really make to the behaviour of the 2 methods on the widget?
var BlahWidget = function(){
this.publicHello = function(){
alert("Hello");
}
};
BlahWidget.prototype.secondHello = function(){
alert("Second Hello");
}
My understanding was that using .prototype allows it to be called by inherited objects. But turns out that this is not the case. Both methods can be called by the inherited function objects, as shown below:
var MiniBlah = function(){
this.callSupers = function(){
this.publicHello();
this.secondHello();
}
}
MiniBlah.prototype = new BlahWidget();
MiniBlah.prototype.constructor = MiniBlah;
var x = new MiniBlah();
x.callSupers();//calls both publicHello and secondHello
The difference is that functions declared on the prototype object are shared across instances of objects created by a constructor function whereas functions declared inside of the body of a constructor function are not, they belong to the object constructed from the function.
What this means in practice is that you could create a load of objects from a constructor function with a function on the prototype doing X, then change that function on the prototype to do Y and all object instances will get the new functionality of the function.
An example
var BlahWidget = function(){
this.publicHello = function(){
console.log("Hello");
}
};
BlahWidget.prototype.secondHello = function(){
console.log("Second Hello");
}
var blah1 = new BlahWidget();
var blah2 = new BlahWidget();
blah2.publicHello = function() {
console.log("Goodbye");
}
blah1.secondHello(); // logs SecondHello
blah2.secondHello(); // logs SecondHello
BlahWidget.prototype.secondHello = function(){
console.log("Second Goodbye");
}
blah1.secondHello(); // logs Second Goodbye
blah2.secondHello(); // logs Second Goodbye
blah1.publicHello(); // logs Hello
blah2.publicHello(); // logs Goodbye
Every single instance of "BlahWidget" will have its own distinct copy of the "publicHello" function.
Also, though this is just academic, I'm not sure I'd say that "prototype" is a keyword; it's more like a "special property name".
In JavaScript Functions are so powerful to build OOPs and modular concepts. Following concepts are implemented using Function only in JavaScript:
Method
Class
Constructor
Module
Below code shows the code which create class MyClass and it has private members:
function MyClass(a) {
var count = 3; // private member
// this check function is private function
function check() {
if (count > 0) {
count--;
return true;
}
else {
return false;
}
}
this._a = a;
this.get = function () {
if (check()) { // use of private function
return this._a;
}
else {
return "Thullu"; // after invoking get method 3 times in the object this else will be executed
}
}
}
In the above code variable, count is private as any object created from MyClass will not have this variable similarly function check() is private function as this function is not part of this in the MyClass. When we create an object of MyClass using new keyword this is returned. This concept is possible in JavaScript because of lexical scoping (functional scoping).
When we create object of this class MyClass, and call the get method more than 3 times:
I would like to write few points regarding new keyword.
When a function is called with the new operator, a new object is created with prototype members and assigned to this.
Above statement is true only if there is no explicit return value in the function. If explicit return is present in Class (function), then same return will be assigned to the object.
I would like to give here one more example with very basic functionality like in all OOP languages we have. We declare private field and then use public properties to expose the private field, in more formal and OOPs way we create Get and Set method to update private field or retrieve private member of class.
Same get and set functionality for private variables in JavaScript we can achieve as shown in below example:
// private class with get and set methods
function MyClass() {
var _privateField = 0; // It is private field as it is not part of "this"
this.GetPrivateField = function () {
return _privateField;
};
this.SetPrivateField = function (value) {
_privateField = value;
};
}

Categories