I want to understand how we can declare a variable inside the class?
For example, Until now, I have been declaring it like this
let displaySearchCrypto = []
let updateCoinData = [];
class cryptoTicker extends PureComponent {
and using it throughout my class (I mean inside my class like this)
componentDidUpdate() {
updateCoinData = [...this.props.cryptoLoaded];
if (updateCoinData[i]["short"] == tradeMsg.coin ) {
//Search for changed Crypto Value
updateCoinData[i]["long"] = tradeMsg["message"]["msg"]["long"]
updateCoinData["short"] = tradeMsg["message"]["msg"]["short"]
or
search = () => {
displaySearchCrypto.push({
no: {i},
key: this.props.cryptoLoaded[i]["long"],
short: this.props.cryptoLoaded[i]["short"],
long: this.props.cryptoLoaded[i]["long"],
price: this.props.cryptoLoaded[i]["price"],
mktcap: this.props.cryptoLoaded[i]["mktcap"],
perc: this.props.cryptoLoaded[i]["perc"],
vwapData: this.props.cryptoLoaded[i]["vwapData"]
})
But, Since I am going to use inside a single class only, I think I shouldn't declare in global scope class. So my question is, How to declare a variable inside the class?
You don't declare variables inside a class. You declare variables within a constructor or method, or you create properties of an instance (or the class itself, "static" properties, which are properites on the constructor function).
If you're using modules, your first code block won't create globals, it will create module-globals (global only to code in that module). If that module contains only that class, and you mean for the variables and the arrays they refer to to be shared by all instances of that class, you can keep doing it that way.
But I suspect you want them to be properties of the instance, not shared between instances, in which case you define those properties in the constructor:
constructor(props) {
super(props);
this.displaySearchCrypto = [];
this.updateCoinData = [...this.props.cryptoLoaded];
}
Then use them by referring to the instance (usually via this.).
Yes I think T.J Crowder anwsers this very nicely. However I would like to add the following:
The task of Objects and classes is to provide abstractions of certain entities. In the case of ReactJS these objects are react components. The advantage of putting all the data related to a certain component inside an object provides the following advantages:
Everything inside the object is automatically namespaced, this helps in preventing potential naming conflicts
We can hide some of the implementation details inside the object. Then use this object in another place where we don't have to bother with how a certain methods are implemented, we just have to know how to interact with it.
Also remember:
Classes have:
No variables but properties which are associated with the object.
No functions but methods which are associated with the object.
Furthermore it is important to know that JS uses prototypal inheritance. The class keyword is merely syntactic sugar build on top prototypal inheritance.
Related
I am new to learning objects and classes in Javascript. I was just wondering, why would you attach a static method to a class, like so:
class MyClass {
static myFunction(){
console.log('foo');
}
}
When you can just declare a regular, custom function outside of the class like one usually does?
function myFunction() {
console.log('foo');
}
A static "method" is just a regular function that is attached to a class. This is useful when it belongs to that class semantically, and in extreme cases necessary in an inheritance hierarchy. The class name provides a visual namespace for accessing the function, e.g. Map.from does something different than Set.from.
However, you would only ever do that when you already have an existing class. You would never create an empty class only to put a static method inside it. In such a case, a simple object literal with a regular object method suffices:
const MyObject = {
myFunction() {
console.log('foo');
},
};
MyObject.myFunction();
Mostly for namespacing. Imagine you need 10 functions of related feature. Instead of taking up 10 names from global scope, using static methods you use just one global name, being the class name.
Remember that apps often end up being complex, using 3rd party libraries. Name clashes is a real problem when complexity comes to play.
My initial page load instantiates PageInit as follows.
<script>
"use strict";
let PageInit = null;
document.addEventListener("DOMContentLoaded", () => {
PageInit = new IPageInit();
});
</script>
I had to let PageInit=null in order to put that reference into the global name space to make it visible. I suspect that is wrong, because I can't imagine that every class that is instantiated has to be done so in global. (??) So, guidance on the right way to do this is appreciated also.
PageInit(), once it is created has a constructor that calls a class method, which in turns creates an instance of another class:
class IPageInit {
constructor() {
this.InitialiseComponents();
}
//Class Method
InitialiseComponents() {
this.PageContent = new IPageContent();
}
}
Coming from a C# background, I do not create an instance of a class with the class's exact name, as you see above. The class name is "IPageContent", and the instantiated name is just "PageContent". (Again, guidance on the right naming conventions is appreciated.)
PageContent(), when it is instantiated has a constructor that itself creates a property called "TrafficData".
class IPageContent {
constructor() {
this.TrafficData = "Paragraph 13.5";
}
}
Later, in "loose javascript" code on the page, a function tries to make a reference to TrafficData. I've tried two ways:
// page javascript
function LoadTrafficData {
let x = PageContent.TrafficData; // PageContent (itself) is undefined
let x = PageInit.TrafficData; // PageInit is valid object, but TrafficData is undefined
}
As you see, neither way works. I do not know enough about scope and visibility in instantiated JavaScript classes to figure out what is wrong and what to do about it. I am using plain vanilla JS - no frameworks, APIs, or Libraries.
How do I get LoadTrafficData() (a loose function, not a class method) to get a reference to TrafficData?
You are correct that global variables are generally a bad practice. Modern js uses imports to import classes into other classes. For example, you might have a PageService singleton class that creates an instance of your PageContent class and holds it in a class property. Other classes could import your PageService singleton to use its properties.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
Your naming conventions are a bit unusual for JS as well:
Class names are normally capitalized, like PageContent, and instances are lowercase, like pageContent.
Class methods and functions should start with lowercase letters.
In typescript, you would prefix interfaces with an I, like IPageInterface, but you wouldn't normally prefix class names in regular javascript.
To debug your stuff, it's common to do console.log(myVariable) to inspect things. You can also insert a debugger; statement in your code to launch chrome's debugger at that line. To access your global var, you would do: PageInit.PageContent.TrafficData.
I am trying to figure out what is different between defining local/private properties and methods inside a class compared to WeakMap constructor?
is the purpose of hiding them from outside are the same or is there other thing to use them?
Given your current implementation:
Your let x isn't very useful, because it can only be referenced in the constructor. It can't be used in any of the prototype methods. The WeakMap, on the other hand, can be referenced anywhere. That's a pretty big difference.
Your WeakMap can be referenced anywhere. This means that it's not actually providing any privacy; anything with a reference to an instance and the WeakMap may access the radius value that you wanted to be private.
If you wanted the WeakMap to be properly private, via closures, you could use an IIFE to define the class, eg:
const myClass = (() => {
const weakMap = new WeakMap();
return class Circle {
// etc
})();
That way, the top level only has a reference to the myClass, and not to the weakMap.
I would use your let x in the constructor whenever a variable is only needed in the constructor - not necessarily for the sake of hiding data, but just because it has no use outside of the constructor. See Why is it good programming practice to limit scope?
Note that there is currently a proposal for class fields which will probably eventually be implemented, which includes syntax for private fields, eg:
class Circle {
constructor(radius) {
this.#x = radius;
// ...
This will allow #x to be accessed from anywhere within Circle, but nowhere else. It's functionally equivalent to the WeakMap implementation.
This is going to be a relatively long question, but one I would really like to understand. Final question formulated at the bottom of the question.
I have read the answers to this question:
ES6 class variable alternatives
The question on why this is not accepted syntax in ES6:
class MyClass {
const MY_CONST = 'string';
constructor(){
this.MY_CONST;
}
}
1) The first answer mentions:
Remember, a class definition defines prototype methods - defining
variables on the prototype is generally not something you do.
I don't get this; static variables in a class based language would appear to serve the same purpose as properties defined on the prototype in JS.
Obviously not an instance variable like a person's name, but it could be a default MAX_SPEED for a vehicle, or a counter that is shared by all instances. If the instance doesn't override the prototype's MAX_SPEED, it returns to the default. Isn't that the exact purpose of a static variable?
2) The following post (ES6 spec proposal) formulates:
There is (intentionally) no direct declarative way to define either
prototype data properties (other than methods) class properties, or
instance property.
Class properties and prototype data properties need be created outside
the declaration.
I don't see the actual difference in declaring / initialising an instance/class variable with default value within the class itself (outside the constructor)? What does it matter if it's on the prototype? If it concerns an instance variable with a default value that will be likely for all instances (yet overridable), I don't see what is the problem. So what is this intention about exactly?
3) The second answer on the question ES6 class variable alternatives confuses me (though not from a technical pov).
From within a class method that variable can be accessed as
this.constructor.foo (or MyClass.foo).
These class properties would not usually be accessible from to the
class instance. i.e. MyClass.foo gives 'bar' but new MyClass().foo is
undefined
This indicates that it is clearly possible to declare a class variable on the class (or underlying function) as implemented in this example: http://www.es6fiddle.net/iehn0hxp/
class Car{
constructor(){
//Set instance variable
this.instance_var = 220;
//Set class variable
this.constructor.class_var = 240;
}
}
var Mercedes = new Car();
var Audi = new Car();
//Instance property
console.log(Mercedes.instance_var); //220
//Class property
console.log(Car.class_var); //240
//Set instance property
Mercedes.instance_var = 120; //Well I don't know really :-)
console.log(Mercedes.instance_var); //120
//Class property
Car.class_var = 140;
console.log(Car.class_var); //140
//Can be accessed from the constructor property on the instance
console.log(Mercedes.constructor.class_var); //140
console.log(Audi.constructor.class_var); //140
So in the end it is possible to declare a static property from within the class; so I don't see what is the difference declaring it within the constructor, versus just defining it on the class, vs defining it from outside? In the end it just seems to be a trivial technical modification to put it in the constructor vs as an actual class definition (the result will be the same).
Is it really just a design choice to only make methods available?
Ultimate question:
Because I don't understand how being a prototype-language changes the
philosophy of having properties on the prototype against
static variables on a class. It looks the same to me.
I hope that my question is clear, shout if not.
I don't get this; static variables in a class based language would appear to serve the same purpose as properties defined on the prototype in JS.
No, static variables are more like properties defined on the constructor. Variables on the prototype would be closer to instance variables, but they’re not nearly as useful because they’re shared between instances. (So if you modify a mutable property on the prototype, it will be reflected in all other instances of that type.)
This also answers your other questions, I think, but to recap:
variables on the prototype are not like static variables in that they appear to belong to every instance rather than just the class
variables on the prototype are not like instance variables in that each instance of the class doesn’t have its own instance of the variable
therefore, variables on the prototype are not that useful and they should be assigned to in the constructor (instance variables) or assigned to the constructor (class variables)
they’re also properties, not variables
And a non-ES6-sugared example:
function Something() {
this.instanceProperty = 5;
}
Something.staticProperty = 32;
Something.prototype.prototypeProperty = 977;
var s = new Something();
console.log(s.instanceProperty); // 5
console.log(s.prototypeProperty); // 977? If you want a class property,
// this is not what you want
console.log(s.staticProperty); // undefined; it’s not on the instance
console.log(Something.staticProperty); // 32; rather, it’s on the class
console.log(Something.prototypeProperty); // undefined; this one isn’t
I'm learning Javascript and have several questions concerning Javascript and OOP. I've noticed different declarations of functions in "classes" in various tutorials. First is the inside constructor:
Class = function () {
this.doSomething = function() {....};
}
And the other one is:
Class = function () {}
Class.prototype.doSomething = function() {....};
In which situations should the first construction be used, and in which situation should the second construction be used?
And the other question is: have I understood correctly that there's no protected properties or methods in js? What is to be used instead?
Thank you in advance!
When you define a function inside the constructor as this.myFunction=..., it is specific to your instance. This means that it must be constructed and kept in memory for all instances, which may be heavy. It also can't be inherited .
The only valid reason to do this are :
the enclosing of specific values
other types of specific functions (you might build a different function each time)
Most often, what you really need is a function defined on the prototype.
From the MDN on objects :
All objects in JavaScript are descended from Object; all objects
inherit methods and properties from Object.prototype, although they
may be overridden. For example, other constructors' prototypes
override the constructor property and provide their own toString
methods. Changes to the Object prototype object are propagated to all
objects unless the properties and methods subject to those changes are
overridden further along the prototype chain.
Regarding your additional question : the following code builds a non directly accessible function :
Class = function () {
var imprivate = function(){...};
this.doSomething = function() { uses imprivate};
}
A downside is that you have a different function instance for each instance of Class. This is most often done for modules (from which you have only one instance). Personally, I prefer to do exactly as suggested by ThiefMaster in comment : I prefix my private functions with _ :
// private method
XBasedGrapher.prototype._ensureInit = function() {