I know that ES6 solved a lot of problems that existed with the this keyword in ES5, such as arrow functions and classes.
My question relates to the usage of this in the context of an ES6 class and why it has to be written explicitly. I was originally a Java developer and I come from a world where the following lines of code were perfectly natural.
class Person {
private String myName;
public Person() {
myName = "Heisenberg";
}
public void sayMyName() {
System.out.println("My name is " + myName);
}
}
The compiler will always refer to the value of the field myName, unless it has a local variable with the name myName defined in the scope of the method.
However, once we convert this code to ES6:
class Person {
constructor() {
this.myName = "Heisenberg";
}
sayMyName() {
console.log(`My name is ${myName}`);
}
}
This won't work and it will throw an Uncaught ReferenceError: myName is not defined. The only way to fix this is to throw in an explicit this reference:
console.log(`My name is ${this.myName}`)
I understand the need for this in the constructor since ES6 classes don't allow your fields to be defined outside of the constructor, but I don't understand why the Javascript engines can't (or won't, because of the standard) do the same as Java compilers can in the case of sayMyName
Maybe I will not directly answer your question, but I'll try to direct the way you should think about JS class keyword.
Under the cover there is no magic about it. Basically it's a syntatic sugar over prototypal inheritance that was since the beginning of JavaScript.
To read more about classes in JS click here and here.
As of why you need explicitly write this is that because in JS it's always context sensitive, so you should refer to exact object. Read more.
Related
I was trying ES6 syntax and find I cannot define prototype property or instance property within class defination, why forbids it?
I was using MyClass.prototype.prop=1 before, try ES7 by babel compiler as below, still cannot define prototype property.
class MyClass{
prop=1;
static sProp=1;
}
I don't think define instance property is any dangerous, there's 2 cases in my own browser game need prototype property:
Subclass instances need to inherit same property value from base class:
var Building=function(){...}
Building.prototype.sight=350;
TerranBuilding.CommandCenter=...(CommandCenter extends Building)
TerranBuilding.Barracks=...(Barracks extends Building)
So CommandCenter and Barracks will both have same building sight as 350.
new CommandCenter().sight===new Barracks().sight//All buildings have same sight
Buffer effect override original property and remove buffer
Marine.prototype.speed=20
var unit=new Marine()
unit.speed===20//get unit.__proto__.speed 20
unit.speed=5//Buffer:slow down speed, unit.speed will override unit.__proto__.speed
delete unit.speed//Remove buffer
unit.speed===20//true, speed restore
So I think it should add a way to set prototype property instead of forbid it completely, or can you give some other solutions to deal with above 2 cases?
Updated Answer (April, 2022)
Just two months after my previous answer, in August of 2021, the static block proposal was moved to stage 4 by the TC-39 committee. See the whole informal list of finished proposals here.
For those looking to get a use case summary of static blocks in Javascript, read the initial publication from the V8 blog from March 2021, after their implementation.
Also, see the MDN documentation for static initialization blocks.
Though most all updated browsers now support this, read below if you really like to support Internet Explorer.
Original Answer
Below is the typical pattern I follow in javascript. Native, no babel, etc..
It mirrors the static-block style that java uses. There is a Stage 3 Proposal open for this right now, and I expect therefor, that it will be standardized in the near future (as is consistent with the stage 3 proposal expectations of the TC-39 committee).
What the proposal will look like
class MyClass {
static {
// Any code here is executed directly after the initialization
// of MyClass. You can add prototype stuff here. The function
// is called bound to `MyClass`.
}
}
This can be done today using a static iife
These will function exactly the same way.
class MyClass {
// Using private properties is not required, it is just an option. Make
// sure to use an arrow function so that `this` refers to `MyClass`,
// Note that `MyClass` will still be in the functions closure.
static #_ = (() => {
// 'Almost' how functions are typically added. ES6 style
// is always recommended over this.
this.prototype.myFunc = function myFunc() {
console.log(":D");
};
// ES6 would actually do this (approximately) so that the function is
// non-enumerable in the prototype.
Reflect.defineProperty(this.prototype, "myFunc", {
// enumerable: false, // defaults 'false'
writable: true,
configurable: true,
// I'm intentionally not using the shorthand for the function
// so that it is named 'myFunc'.
value: function myFunc() {
console.log(":D");
}
});
// Note that all children of MyClass will refer to this exact
// object if put in the prototype, i.e. not a copy of it.
// Also, this property will be non-enumerable on the children
// (but enumerable on the prototype itself unless you
// use `defineProperty` as above).
this.prototype.sharedProperty = { name: "Gerald" };
})();
}
Neither of those will be on the class prototype.
The class Foo { bar = 1; } syntax will assign a value to the class instance, to be accessed with this.bar.
The class Foo { static bar = 1; } syntax will assign a value to the class constructor, to be accessed with Foo.bar.
There isn't much reason to use the prototype in this case. It will only complicate who actually owns the property and assigning a number in a few different classes will have very little overhead.
I would suggest the class instance property and just use this.sight everywhere you need it.
The simplest way to add a property to the prototype inside the class body is by using the prototype assignment as a "value" for a dummy static property:
class MyClass {
static _dummy = MyClass.prototype.prop1 = <expression1>
static _dummy = MyClass.prototype.prop2 = <expression2>
// or
static _dummy = this.prototype.prop2 = <expression2>
}
(it works without parentheses because = is right-associative, and it's fine to re-use the same dummy property for each prototype assignment)
If you want to do more interesting (multi-line) computation for the values, an initializer can be an immediately-executed function expression, in which case you've basically created a static constructor and you can put all the initializations for the prototype and class object in that.
I think the other answer didn't get the point of this question. The whole point of having inheritance is that you can decide when and where to override something. and if anyone think that's an overhead, why does ya use an OOP language at all?
I don't know why it's "forbidden" after all, but I could share some ideas.
I'm pretty sure there is no way to define a Prototype Property with 'class' keyword. Any definition will be install on "hasOwnProperty". A huge setback is that in a constructor, there is no way to have any parents' constructors to interact with an overridden property.
To the point of reasoning, it's actually expelled by an other feature: you can use expressions to assign properties to this.
class A extends B { sight = this.getSight() * 3 }
When an expression excuses, it is either run with instance - created with constructor, or run at class declaration - when the prototype is created.
Accessors and methods don't have this problem. They are defined at prototype definition time and called at instance run time.
Property defined with expression with "=" is the return value of the expression. It is excused right after definition - should be the instance creation time, otherwise this could not be available.
So it's nothing about patterns. It's about having expressions or having inheritance. I definitely prefer inheritance, expressions are so pointless when you can write them right into the constructor.
class A extends B { constructor() { this.sight = this.getSight() * 3 }
Using decorators are a nice work around. You can always do something with the prototype in javascript:
#B({sight:2}) class A {};
decorator B is:
function(option) {return function(clazz) {clazz.prototype.sight = option.sight; return clazz}}
Using Class static initialization blocks1:
class MyClass {
static {
this.prototype.prop = 1;
}
}
console.log(MyClass.prototype.prop); // 1
const instance = new MyClass();
console.log(instance.__proto__.prop); // 1
this in the static block differs as1:
The this inside a static block refers to the constructor object of the class.
The code inside the static block is executed only once when the class initialization gets evaluated.
Note: Safari doesn't support this feature as of June 2022. You can check the latest info on, for example, mdn web docs1.
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_static_initialization_blocks
class MyClass {
constructor() {
MyClass.prototype.prop2 = "Marry";
}
}
const mc = new MyClass()
mc.__proto__ // { prop2: "Marry" }
With the release of ECMAScript 6 on June 2015, Javascript classes syntax was introduced.
This syntax:
class Polygon {
constructor(width, height) {
this.width = width;
this.height = height;
}
}
is basically same as:
function Polygon(width, height) {
this.width = width;
this.height = height;
}
So what is the benefit of using class instead of traditional function?
And in what condition I should use class instead of function?
There are some differences between Class and Function - most people will start by saying that the Class is "just syntax sugar", but that sugar does matter quite a bit. When the JS parser is processing the JavaScript code the parser will save them in different AST nodes, like shown here the ClassDeclaration and ClassExpression are different node types in the resulting AST tree:
https://github.com/estree/estree/blob/master/es2015.md#classes
You can see that for this parser, the new ES6 Classes spec introduces a number of new AST elements to the syntax:
ClassBody
MethodDefinition
ClassDeclaration
ClassExpression
MetaProperty
Since the AST syntax is not standard, there can be more or less types depending on the parser, but what is important to notice that when the code enters the class declaration or class expression it will be interpreted differently by the JavaScript engine.
This means, that Class and Function declarations can not be exchanged. You can see this if you try to write
class notWorking {
return 1; // <-- creates a parser error
};
This is because when the parser encounters the class -keyword, it will start treating the following code as ClassBody of either ClassDeclaration or ClassExpression and then it expects to find MethodDefinitions.
This is a small problem, because creating private variables becomes a bit more challenging. The function declaration could define a private variable neatly like this:
function myClass() {
var privateVar;
}
The class declaration can not have this:
class myClass {
var privateVar; // ERROR: should be a method
}
This is because the syntax of class allows only methods to be declared inside the class body. At least right now.
However, there exists a proposal for creating private fields:
https://github.com/zenparsing/es-private-fields
Thus, in the future you might be able to say
class myClass {
#privateVar; // maybe this works in the future?
}
There is a separate answer considering the private properties in ES6 Classes, which is suggesting some workarounds, like the use of Symbols:
Private properties in JavaScript ES6 classes
var property = Symbol(); // private property workaround example
class Something {
constructor(){
this[property] = "test";
}
}
Naturally there are more differences between classes and functions. One of them is Hoisting 1 - unlike Functions, you can't declare the Class anywhere in the scope:
An important difference between function declarations and class
declarations is that function declarations are hoisted and class
declarations are not. You first need to declare your class and then
access it
The Class declarations and Function declarations are quite similar;
function foo1() {} // can be used before declaration
class foo2{} // new foo2(); works only after this declaration
The class expressions work quite similarly to function expressions, for example they can be assigned to a variable:
var myClass = class foobar {};
More differences are 1
The Class expression / declaration body is always executed in Strict mode - no need to specify that manually
Classes have special keyword constructor - there can be only one of them, or error is thrown. Functions could have multiple definitions of variable of function named "constructor"
Classes have special keyword super which relates to the parent classes constructor. If you are inside the constructor you can call super(x, y); to call the parent class constructor but inside the Method you can call super.foobar() to create call to any parent class function. This kind of functionality is not available for standard Functions although you might emulate it with some custom hacking.
Inside class body you can define function with static keyword so it can be called using only ClassName.FunctionName() -syntax.
Both class declarations and expressions can use extends keyword like class Dog extends Animal
MethodDeclaration does not need function -prefix, thus you can define function "ok" inside the class "m" like this: class m { ok() { } }. Actually it is not even allowed to define function as class m { function ok() { } }
However, after the parser has completed it's job, the class instance is essentially running the same way as any other object.
The new ES6 Class syntax is essentially more clear way of expressing objects in a traditional OOP way and if you like it, then you should use it.
EDIT: also, the ES6 Class syntax has also another limitation: it does not allow the member functions to use lexically binded using fat arrow. ES7 seems to have experimental feature allowing it. That can be useful for example when binding methods to event handlers, the related question is here.
1 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
class its nothing but a syntactical sugar over javascript logic class creation using function. if you are using a function as class the entire function is act as a constructor, if you want to put other member functions you need to do that in constructor like this.something = ..., or var something = ... in case of private members (if you are not injecting from outside, assume you are creating object with other methods / properties), but in case of class the entire function is not actually act a constructor you can explicitly separate it with other member functions and data.
I've been reading Javascript Patterns by Stefanov recently. And I found this example confusing to me here:
Another case of using a convention to mimic functionality is the private members >con- vention. Although you can implement true privacy in JavaScript, sometimes >evelopers find it easier to just use an underscore prefix to denote a private >method or property. Consider the following example:
var person = {
getName: function () {
return this._getFirst() + ' ' + this._getLast(); },
_getFirst: function () {
// ... },
_getLast: function () {
// ... }
};
In this example getName() is meant to be a public method, part of the stable API,
whereas _getFirst() and _getLast() are meant to be private.
As I understand it, either a method is private or public is defined by the way it was written. For example, if we are talking about a constructor function, then, "this.getFirst() = function(){ ... } " would be a public method where as "var getFirst=function(){...}" would be private.
The example in the book is not a constructor function, tho. And I do believe one can't simply use an underscore to make a method public or private. How, then, shall we make private or public method in an object declared in the way as the example above?
Many thanks!
Javascript doesn't have really private variables / methods. The pattern (underscoring) is just coding convention. See MDN: Private properties. It reads
The above technique (underscoring) is simple and clearly expresses intent. However,
the use of an underscore prefix is just a coding convention and is not
enforced by the language: there is nothing to prevent a user from
directly accessing a property that is supposed to be private.
Meanwhile, you cannot use var getFirst=function(){...} inside Object literal {...} construction.
It looks like it's trying to say that getName(); is an accessor within the same class as the private data member functions.
I am getting into ES6 lately and finally looking into classes seriously. I read that classes are just a cover over Objects in Javascript, however, I am finding the syntax most uncomfortable.
Could someone please explain / point to a reference where they explain, how classes simulate & importantly how we can map them into Javascript way of Object manipulation in our mind.
class NoteStore {
constructor() {
this.bindActions(NoteActions);
this.notes = [];
}
}
As per the example code above, I thought classes are mere constructors, but then what is a constructor doing within a constructor?
As someone who started learning programming with Js, I find the addition of classes (also React's classes) to be a terrible addition to Js so any help would be awesome.
Thanks
Classical class-based programming is based on defining a class which contains a constructor method and other methods which will be inherited by the constructed object. This is written as you show in your sample: the class is defined with its name, then contains a constructor function, then further functions.
The constructor method in a class definition is somewhat special, in that it gets invoked upon object construction. Since it's special, it somehow needs to be marked as such, and that's done by naming it constructor.
In classical Javascript (prototype-based OOP), this works differently: an object constructor is a simple function, and methods inherited by each object instance are defined on an object on the .prototype property of that function. There's nothing special about the constructor in prototype-based OOP, it's just a function, and the real magic lies in the new keyword and the use of this when the object gets constructed.
Expressing this in the form of a class with a constructor method is merely catering to classical-OOP developers, and arguably provides a more compact syntax.
class NoteStore {
constructor() {
this.bindActions(NoteActions);
this.notes = [];
}
bindActions(actions) {
..
}
}
This expressed in simple Javascript is:
function NoteStore() {
this.bindActions(NoteActions);
this.notes = [];
}
NoteStore.prototype.bindActions = function (actions) {
..
}
I think the explanation at MDN is quite clear.
class keyword is nothing but a new name for old style OOP implementation where we use a function constructor to get same functionality.
class keyword is brought to JavaScript to make it more similar to other traditional object oriented languages like C++, Java. But at core it is still function constructor with few changes.
For your question "what a constructor doing under constructor" ES6 has done some modification for older version so that class will not act as a constructor for examaple class cannot be invoked directly(without new keyword) like
NoteStore();
This will throw error in ES6 but if it was a function constructor like in ES5 than it works leaving you in a risk of bugs. classes are also not Hoisted.
For more detail and example you can read this link.
The JS class keyword:
Javascript has a system of inheritance which is called prototypal inheritance. This is a system were objects inherit properties from other objects. When a function is invoked using the new keyword the new object created with it 'inherits' properties from from the constructor function's prototype property.
The JS class keyword is merely syntactical sugar for a constructor function. The class keyword just has different syntax but it essentially achieves the same goal of Object creation with prototypes. Take for example the following snippet:
class human {
constructor (name) {
this.name = name;
}
speak () { console.log('hi')}
};
console.log(typeof human);
// logs function, a class is just a constructor function under the hood
const me = new human('Willem');
console.log(Object.getPrototypeOf(me) === human.prototype);
// logs true, the object me has a reference to the human.prototype object.
me.speak();
// This speak method is located on the prototype of the object, not the object itself
console.log(me.hasOwnProperty('speak')); // logs false
console.log(human.prototype.hasOwnProperty('speak')); // logs true
I see this pattern a lot (which I actually use) but I want an explanation as to how it works.
var mystuff = function() {
var blah = function() {
};
return {
setup: function() {
blah();
};
};
}();
Then usage is very OOP like:
mystuff.setup();
What that's doing is returning a public interface to your object. It looks like you are using the public setup() function to access the private blah() function. This is one method of emulating public and private member functions in Javascript objects.
Since mystuff is defined with that trailing () at the bottom, it's executed immediately when the parser reaches mystuff.setup(), and actually returns an anonymous object (your public interface) with the setup() method.
Others have explained how it works. This is just somemore background info on the topic.
It's called the "Module pattern" (coined by Douglas Crockford I believe, but blogged about earlier).
It gives you three main benefits:
A namespace (the value to the left of "function")
A private "space" to put stuff in (vars, functions, etc) that don't need or should not pollute the global namespace (this is the stuff before the return statement)
A public "space" to put stuff that you want accessible to users of your namespace (this is the return statement)
all in a fairly readable form.
This is simply an example of nested functions in JavaScript. Although the method of calling them may seem "OOP-like" on the surface, this style very much belongs to the functional paradigm.
In essence, however, there's nothing too fancy going on. JavaScript is known as a language in which "everything is a function", which is close enough to the truth. All it means is that any function declared belongs strictly to its parent scope.
It's from a functional programming approach to object oriented programming. Local variables in the outer (anonymous) function (the constructor) are accessible to any function defined within the constructor, but not elsewhere, making the local variables private. Where it differs from the purely functional approach is that the constructor returns an object literal rather than another function. The local variables are accessible by inner functions due to what's termed a closure.
It's use is to create private fields & methods, in the form of local variables.
but I want an explanation as to how it works.
Let's desect it piece by piece.
function() { .... } is a syntax for anonymous function.
function() { .... }() is defining and calling the anonymous function on the same line.
The return value of the function in your sample is an object defined using JSON notation (Javscript Object Notation)
{ setup : .... } is an object with one attribute: it's called setup, and it happens to be a function, in your case.
so, mystuff got the return value, which is an object with a property (function) called setup, and mystuff.setup() invokes this setup function.
Now, the interesting part is probably how setup just calls the blah function, defined inside that enclosing anonymous function.
I believe the technical term here is closure (see the section forming closures) (Also see the wikipedia definition)
Essentially the function becomes like a module of its own, with variables bound to it.
It's explained in crescentfresh's answer
First of all, please avoid this syntax:
var mystuff=function(){...}();
It is bad coding practice since it isn't completely cross-browser as a few browsers will error here.
Get used to putting parentheses around the function like so:\
var mystuff=(function(){...})();
Nextly, regarding the pattern. This pattern is more commonly known as simply "encapsulation" in JavaScript. Closures is another possibly but more specifically it is purely encapsulation in this case.
Encapsulation simply means you are making some members private. What is private in this case? Well the blah variable is private in this case. Please get into the habit of proceeding private members with an underscore to indiciate they are private. It is good coding practice to distinguish public methods from private methods with an underscore.
<script type="text/javascript">
var obj=(function(){
//private members
var _p={};//toss all private members into a single object.
_p.list=[];
_p.init=function(){
_p.list=[];
};
//public members. use "this" to reference object followed by the method.
//however obj._p.list won't be accessible to the global scope
return {
reset:function()
{
_p.init();
}
,addName:function(str)
{
_p.list.push(''+str);//limit to strings
}
,getNames:function()
{
return _p.list.slice(0);//return a clone
}
,alertNames:function()
{
alert(this.getNames().join(","));
}
,getPrivateObj:function()
{
return _p;
}
};
})();
obj.alertNames();
obj.addName("Nandan");
obj.addName("Ram");
obj.alertNames();
obj.reset();
obj.alertNames();
obj.addName("Vinoth");
obj.addName("Kevin");
obj.alertNames();
alert(typeof obj._p);//undefined
var privateObj=obj.getPrivateObj();
alert(typeof privateObj);
alert(privateObj.list.join("|"));
</script>