I was reading about the new JavaScript-like language from Microsoft called TypeScript. In the playground (example section), there is a simple class in TypeScript syntax converted to JavaScript code. Coming from a Java programming background, it was interesting for me to learn how OOP is done in JavaScript as compiled from TypeScript.
The TypeScript code:
class Greeter {
greeting: string;
constructor (message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
var greeter = new Greeter("world");
var button = document.createElement('button')
button.innerText = "Say Hello"
button.onclick = function() {
alert(greeter.greet())
}
document.body.appendChild(button)
And the equivalent JavaScript code:
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
var greeter = new Greeter("world");
var button = document.createElement('button');
button.innerText = "Say Hello";
button.onclick = function () {
alert(greeter.greet());
};
document.body.appendChild(button);
The Typescript part is very similar to Java so I understand that. Now my question is why in JavaScript the body of the Greeter class is embedded in a an anonymous function() call?
Why not write it like this?
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
What is the advantage/disadvantage of each method?
The following is called an Immediately Invoked Function Expression:
(function(){ ... })();
It is used to keep the global scope clean. Though, in this case it isn't necessary since the return value is assigned to a variable Greeter. The only time this pattern is useful is when you want "private" static members.
E.g.:
var Greeter = (function () {
var foo = 'foo', bar = 'bar'; /* only accessible from function's defined
in the local scope ... */
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
This is to allow for private members. In this example, all members are public so your two constructions are equivalent. However, if you want to provide for private members you need to hide them from the calling scope via a closure. Thus if you have a private member like so:
class Greeter {
private greeting: string;
constructor (message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
You would probably get something like this:
var Greeter = (function () {
var greeting="";
function Greeter(message) {
greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + greeting;
};
return Greeter;
})();
The greeting variable will be available to any function defined inside the anonymous function, but invisible everywhere else.
Besides the obvious scoping/closure reasoning. Using an anonymous function that invokes itself immediately pre-loads (interprets) the class definition. This allows any JIT optimizations to be front loaded within the execution. In short, for larger more complex applications it will improve performance.
The anonymous function / self executing closure is usually used to encapsulate scope so that only the returned value is accessible outside of it. (or anything you attach to other objects, like window)
The anonymous function is probably there to prevent name collition with other parts of the code. Think of it this way, inside your anonymous function, you could even declare a variable called "$" to be whatever you want, and at the same time, be using jQuery on other parts of your code without conflict.
The closure is the sole mean to call the constructors with parameters:
var w = new Greeter("hello")
There are other methods but all complicated and with limitations and drawbacks.
Related
Let's say, I want to produce an output of "Hello World" (that is passing this.name as "World"). How do I access the inner m function
var A=(function(){
function Person(name){
this.name=name;
console.log(name)
}
var m=function(){
return "Hello " + this.name;
};
Person.prototype.getGreeting=m;
return Person;
})();
What you have is a module pattern where you have a constructor Person which is returned.
(function(){})()
is called an IIFE. Its used to create abstractions. So for example, m is accessible inside that block but not outside.
Person.prototype.getGreeting=m
is exporting function that as a part of class. In traditional sense, its like method on abstract class. Any method part of prototype is accessible to all instances
var A = (function() {
function Person(name) {
this.name = name;
console.log(name)
}
var m = function() {
return "Hello " + this.name;
};
Person.prototype.getGreeting = m;
return Person;
})();
const person = new A('Foo');
console.log(person.getGreeting())
References:
What are IIFEs
Prototypes in JS
This question already has answers here:
What is the (function() { } )() construct in JavaScript?
(28 answers)
Closed 4 years ago.
I was following a tutorial where they used a translator to translate a class in Typescript into javascript. The translated javascript is a bit confusing and I was wondering if someone can explain to me what the code is doing.
Original Typescript:
class Greeter {
greeting: string;
constructor(message: string){
this.greeting;
}
greet(){
return "Hello, " + this.greeting;
}
}
and the translated Javascript:
var Greeter = (function(){
function Greeter(message){
this.greeting = message;
}
Greeter.prototype.greet = function(){
return "Hello, " + this.greeting;
};
return Greeter;
}());
I am confused about this part (function() { ... }());
what is the first () doing? why is the function(){} necessary? and what is the following () doing?
The syntax is pretty confusing and I hope someone can explain this.
I am confused about this part (function() { ... }());
IIFE this function will executed as soon as it is interpreted by the browser. You don't have to explicitly call this function.
what is the first () doing? why is the function(){} necessary?
All functions in javascript are Object by nature. To create a instance of it you have to call like new Greeter() so the context this is set properly. If executed like Greeter() now the context this is from where it's executed. In most cases it's the window object.
Reference articles
https://www.phpied.com/3-ways-to-define-a-javascript-class/
https://medium.com/tech-tajawal/javascript-classes-under-the-hood-6b26d2667677
That's called IIFE.
General syntax:
(function () {
statements
})();
But sometimes, you can write:
(function () {
statements
}());
I usually use the second's because it's following these steps:
Defining a function: function () { /* statements */ }
Calling the function: function () { /* statements */ }()
And wrapping the function: (function () { /* statements */ }())
Or use it with as an asynchronous thread:
(async function () {
// await some task...
})();
(async () => {
// await some task...
})();
You can also use it to define some local variable(s), like this:
let Person = (function () {
let _name = null;
class Person {
constructor(name) {
_name = name;
}
getName() {
return _name;
}
}
return Person;
}());
let person = new Person('Harry');
console.log(person.getName());
console.log(window._name);
For modules, you want to create some plugin(s) and make it to be global, you can write:
(function (global, factory) {
// we can use "global" as "window" object here...
// factory is a function, when we run it, it return "Person" class
// try to make it global:
global.Person = factory(); // same to: window.Person = factory();
}(window, function () {
class Person {};
return Person;
}));
This construct:
const foo = (function() { })();
Creates an anonymous function, and immediately calls it. The result gets places into foo.
It's possible to split this up in more lines with an extra variable:
const temp = function() { };
const foo = temp();
The reason typescript does this, is because placing code in function creates its own new scope. This makes it possible to do certain things without changing the global namespace.
(function() { ... }()); is a form of IIFE (Immediately Invoked Function Expression)
For example:
var Greeter = (function(){
return 1;
}());
The result is equal to
function fn() {
return 1;
}
var Greeter = fn();
The value of Greeter is 1 after executing the above codes. But the former one uses anonymous function and the latter one declared a variable fn to store the function.
Greeter.prototype.greet = function(){
return "Hello, " + this.greeting;
};
This code snippet is to define a function on the prototype of object Greeter so that this function can be inherited when you create new Greeter(). You may refer to Object.prototype
I'm not getting what's happening in the below code. Why constructor function is enclosed inside another function and why both constructor and the function in which it is enclosed have given the same name? Also why enclosing function has made to be self invoked?
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
}());
var greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
In this particular case there's no point in wrapping Greeter in an immediately invoked function (IIFE); Ravindra Thorat is right that rewriting results in (mostly) equivalent behavior.
This construct starts to make sense when you put more stuff inside the anonymous-immediately-executed-function, like the strict mode marker or a private variable (GREETING in example below):
var Greeter = (function () {
"use strict";
const GREETING = "Hello, ";
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return GREETING + this.greeting;
};
return Greeter;
}());
var greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
// console.log(GREETING) // not defined here -- only available inside the anonymous function
Updated to answer a comment:
Note that the value of the outermost variable Greeter is not the outer anonymous (nameless) function itself, but the result of its invocation. Compare:
var Greeter = (function() {...})() // the returned value is assigned to Greeter
var Greeter = (function() {...}) // the anonymous function without parameters is assigned to Greeter
Since the outer anonymous function ends with return Greeter, the value of the outermost Greeter variable is the function Greeter(message) declared inside the IIFE.
Basically everything inside the IIFE is unavailable outside it, except the explicitly returned object (the Greeter(message) constructor in this example).
You can consider the self-invocation function as kind of higher order function, that returns some another function with some configuration.
Okay, what that self-invocation function is doing? It does contain one constructor functions which hold one public property with name "greeting". Input parameter received from constructor function, get assigned to the greeting. After this signature, it's adding some helper function to this constructor function, with the help of prototype, which prints greeting message.
what does it mean by prototype? it's the one of the major pillar of javascript https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
Well! do we really need a self-invocation function for this? the answer is, nope! we can have this written in a simple way too, just like below,
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
var greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
That's it! And it will give the exact result as above.
Then why that guy used the self-invocation function for it? I believe, cool design pattern always shines. That guy has a plan to write some factory function kind of thing which would give me a fully configured constructor function. In this case, the self-invocation expression is nothing but the so called factory.
Note: in the original post by you, the outer most Greeter is not a real function, that is a simple variable which holds some function, returned by that self invocation block. You can use any name for that variable.
I'm trying to understand the difference between 2 different function declarations in JavaScript.
Consider the following code snippet:
function SomeFunction(){
this.func1 = function(){
}
function func2(){
}
}
What is the difference between the declarations of func1 and func2 above?
In simple language,
fun1 is a property of SomeFunction class holding a reference of anonymous function where func2 is named function.
Property
Here fun1 is property of that SomeFunction class, it means when you create instance of SomeFunction class using new keyword, then only you can access it from outside.
Private Method
Here fun2 will work as private method of class SomeFunction, and will be accessible inside that class only.
Sample
function SomeFunction() {
this.func1 = function() { console.log("in func1") }
function func2() { console.log("in func2") }
}
var obj = new SomeFunction();
obj.func1(); //Accessible
obj.func2(); //Not accessible
This way of declaring functions is called Function Expression. This kind of functions can be called only after definition of the function. Function expressions load only when the interpreter reaches that line of code.
var func1 = function() {
// Code here
}
This way of declaring functions is called Function Declaration. Function declarations load before any code is executed. So it can be called anywhere in the program before it's definition. For reason, read about Hoisting in Javascript
func1 () {
// Code here
}
When defining these inside another function, Function Expression acts as the property of the function and can be accessed using the object of the parent function. Whereas, the scope of Function Declaration is inside the parent function, so it is not accessible from outside the parent function. This is a very important property in Javascript using which we can simulate the Object Oriented Nature.
In brief, Function declaration acts as Private method of a class and Function Expression as Public method.
Here is the working example below to understand more about it.
function SomeFunction(){
this.func1 = function() {
console.log('Public function.')
}
function func2() {
console.log('Private function.')
}
this.func3 = function() {
func2();
}
}
var obj = new SomeFunction();
obj.func1(); // Public Function.
// Can be accessed as it is a Public function
obj.func3(); // Private Function.
// Can be used to access a private function.
obj.func2(); // Error: Uncaught TypeError
// Private function
Hope this helps! :)
function SomeFunction() {
// Function Expression
this.func1 = function() {
}
// Function Declaration
function func2() {
}
}
Update:
Based in your question: What is the best way to declare functions within a Javascript class?
In OOP programming a Class has attributes and methods.
In the following sample code, the Person class contains:
(2) Attributes:
name
country
(1) Method:
showPerson1()
function Person(name, country) {
// Attributes of Person class.
this.name = name;
this.country = country;
// Function Expression:
this.showPerson1 = function() {
var personMessage = "Hi, my name is ";
personMessage += this.name;
personMessage += ". I'm from ";
personMessage += this.country;
personMessage += ".";
return personMessage;
};
// Function Declaration:
function showPerson2() {
var personMessage = "Hi, my name is ";
personMessage += this.name;
personMessage += ". I'm from ";
personMessage += this.country;
personMessage += ".";
return personMessage;
}
}
var person1 = new Person("John", "United States");
console.log(person1.showPerson1()); // Prints: Hi, my name is John. I'm from United States.
console.log(person1.showPerson2()); // Throws an error.
As you can see, you can execute the showPerson1() method because is reference to the Person class by using this keyword and using the Function Expression style.
However, you can't execute showPerson2() method because this function was not created like a reference to the Person class.
You can find more information here.
As far as I know your question revolves around scope. Let's say for a second that you had a main class that called upon functions from other classes. Maybe these other classes have a function called func1 that you needed to use. But wait, you want to use the name func1 in your main class as well without mentioning the global function from the other class. Using this.func1 would allow you to access it as a local function, since .this refers to a local scope.
Basically, it allows him to store the result of the function without declaring a separate variable, which is nice since it's only probably going to be used temporarily and in the context of the function in which it was declared.
Additional Reading (Or in case my analogy falls flat):
http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/
https://www.w3schools.com/js/js_function_invocation.asp
The func1 is actually a property on SomeFunction so essentially you can do
const someClass = new SomeFunction();
someClass.func1()
But you cannot do
const someClass = new SomeFunction();
someClass.func2()
because it is not attached to that class. However, you can still use the func2 internally in your class SomeFunction but not outside the class.
ES6 provides more clean syntax to understand this.
class SomeClass{
func1(){
//function body
}
}
Hope this helps
Suppose I have a class (very simple scenario)
class Student
{
name = "John";
sayHello()
{
console.log("Hi, I'm " + this.name);
}
}
It's compiled by TypeScript compiler to:
var Student = (function () {
function Student() {
this.name = "John";
}
Student.prototype.sayHello = function () {
console.log("Hi, I'm " + this.name); //here is the problem. Accessing name via this
};
return Student;
})();
Now if I create an object and call a method, everything works fine.
var student = new Student();
student.sayHello(); //prints Hi, I'm John
But if I invoke that method from callback, it breaks (this is referencing a Window as expected)
setTimeout(student.sayHello); //prints Hi, I'm
I'm aware of the difference between this in JavaScript and C# or Java. I'm also aware, that TypeScript tries to address this difference. For example this code:
class Student
{
name = "John";
sayHelloTo(other)
{
other(() => this.name);
}
}
Would have been compiled to
var Student = (function () {
function Student() {
this.name = "John";
}
Student.prototype.sayHelloTo = function (other) {
//note, the compiler solves the problem by capturing this into local variable
var _this = this;
other(function () {
return _this.name;
});
};
return Student;
})();
Why isn't the compiler creates something like _this variable in the first scenario for class members? I would expect to see something along next code (not a real output and this code is not correct either, just to show my intention)
var Student = (function () {
var _this;
function Student() {
_this = this; //solves the problem of setTimeout(student.sayHello)
_this.name = "John";
}
Student.prototype.sayHello = function () {
console.log("Hi, I'm " + _this.name);
};
return Student;
})();
I've used the TypeScript v0.9.7 compiler
You might want to change the sayHello function like below to make it generate to code you want. Notice the sayHello = () => { }
This will still work with multiple students which is not the case with your example.
class Student
{
name = "John";
sayHello = () =>
{
console.log("Hi, I'm " + this.name);
}
}
It will generate code like this:
function Student() {
var _this = this;
this.name = "John";
this.sayHello = function () {
console.log("Hi, I'm " + _this.name);
};
}
Another possibility is to change the call to setTimeout like this
setTimeout(() => { student.sayHello() });
The only thing that the compiler could do would be to make sure each constructed object had a bound copy of the prototype functions. That would involve a very significant semantic change, so it can't really do that.
The translated code returns a function that has access to a closure, it's true. However, in your suggested alternative, there's only one _this that would be shared by all instances created by the constructor. The closure is in that function that is called to create the "Student" constructor; that function only runs once, when the constructor is made, and then never again. Thus each call to new Student() would update that single, shared variable _this. (In the example, the way that would cause a problem would be for the "name" property to change on a Student instance. If they all are named "John" it doesn't matter :)
The fundamental issue is that in JavaScript, there is no intrinsic relationship between a function and any object. When you call
setTimeout(student.sayHello, 100);
the first parameter expression evaluates to a plain reference to that "sayHello" function. The fact that the reference came from the object is lost. I suppose another alternative for Typescript would be to catch those sorts of expressions and create a bound function at that point. That is, the class code itself would remain the same, but the setTimeout() call would be translated as
setTimeout(student.sayHello.bind(student), 100);
What sort of ramifications that would have on everything I can't say. I also don't know how hard it would be for the compiler to know that it should do that transformation; there might be times at which it doesn't make sense.