I am writing an application code in javascript.
I just want an expect advice on how Encapsulation be achieved in JS,
The pattern which I wrote is something like,
var app = (function (window) {
// define variables here
// define functions here
return {
init: function () {},
plotGraph: function () {},
plotTable: function () {},
resizeHanlder: function () {},
initMenu: function () {},
attachEvent: function () {}
}
})(this);
Is there anything better than this.
Why I am doing this?
I really do not want to pollute global scope
What you are trying to make is called revealing module pattern. Here is one link on this topic:
https://carldanley.com/js-revealing-module-pattern/
Let's short analyse your code:
There will be only one global variable app. It get assigned the result of an anonymous functions, which is self-executed (we'll see that in the last line), also called Immediately-Invoked Function Expressin (IIFE).
var app = (function (window) {
The function returns an object which is assigned to the variable app
return {
init: init,
plotGraph: function () {},
plotTable: function () {},
resizeHanlder: function () {},
initMenu: function () {},
attachEvent: function () {}
}
The following code will never be executed, as the function already returned a value in the previous step.
function init() {}
And this here makes the function self-executable.
})(this);
Since your code has errors I would give you a simple example how to implement the revealing module pattern:
var hello = (function () {
var sayHello, makeGreeting;
sayHello = function () {
return 'Hello, ';
};
makeGreeting = function (name) {
console.log(sayHello() + name);
}
return {
makeGreeting : makeGreeting
};
})();
Now we have one object hello with one method makeGreeting. There is additional logic within which is not exposed to the end user, because he/she doesn't need to know it or isn't supposed to change those values.
Here is another example for this pattern from my GitHub:
https://github.com/cezar77/roman/blob/master/roman.js
Related
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
Purpose: I need to call sub function within main one;
Function declaration:
var MainFunction = function () {
function NestedFunc1(){
console.warn("NestedFunc1");
};
function NestedFunc2(){
console.warn("NestedFunc2");
};
}
Functions call:
MainFunction.NestedFunc1();
MainFunction.NestedFunc2();
What am I doing wrong?
10x;
you can make it public via a property then
function MainFunction () {
this.nestedFunc1 = function(){
console.warn("NestedFunc1");
};
this.nestedFunc2 = function(){
console.warn("NestedFunc2");
};
}
now you can invoke this function outside by doing
var malObj = new MainFunction();
malObj.nestedFunc1();
However, if you want to still invoke it like MainFunction.NestedFunc1() then make it
var MainFunction = {
NestedFunc1:function (){
console.warn("NestedFunc1");
},
NestedFunc2:function (){
console.warn("NestedFunc2");
}
}
The issue is that both of those functions are isolated within a function scope. Think of them as private functions.
One (of many) solutions could be to define MainFunction as a plain ol' object that has some functions as attributes:
var MainFunction = {
NestedFunction1: function () { .. },
NestedFunction2: function () { .. }
};
Notice that a comma is needed to separate the functions because of the way we are defining them. You then just call
MainFunction.NestedFunction1();
Also note that this pattern is fine as long as you don't wish to have other "private" functions inside that object.
I am writing some Javascript code using jQuery to display specially formatted widgets in a browser. I've had success, but now I'm working on refactoring my code for two reasons.
(1) I wish to be able to easily use the widget more than once and have a Javascript object referring to each one.
(2) I wish to do it the right way so that my code is totally reusable and doesn't little the global namespace with all sorts of objects and functions.
I'm having a scoping problem and I wish to fix the problem and improve my understanding of Javascript scope. I've condensed this problem down to a tiny code snippet that illustrates what I'm doing:
function getMyObject() {
var theObject = {
doThis: function () { },
doThat: function () { },
combinations: {
doThisTwice: function () { doThis(); doThis(); },
doThatTwice: function () { doThat(); doThat(); }
}
};
return theObject;
}
var myObject = getMyObject();
myObject.combinations.doThisTwice();
I've declared a function that returns an object.
However, when I try to execute the function combinations.doThisTwice(), the program throws an error saying that doThis() is out of scope. How do I refer to the function doThis in the scope of combinations.doThisTwice?
Update: Thank you kindly for the answer to my question: Replace doThis() with theObject.doThis() inside the function doThisTwice(). This works, but I don't understand why.
I would have thought that the name theObject would not be valid until the end of the object declaration. I think I must misunderstand some fundamental aspect of Javascript... probably because of the C-like syntax.
You need to do:
function getMyObject() {
var theObject = {
doThis: function () { },
doThat: function () { },
combinations: {
doThisTwice: function () { theObject.doThis(); theObject.doThis(); },
doThatTwice: function () { theObject.doThat(); theObject.doThat(); }
}
};
return theObject;
}
var myObject = getMyObject();
myObject.combinations.doThisTwice();
You reference 'theObject' from an outer scope to call the functions in an inner object.
doThis is not defined in the functions scope, so it will traverse up the scope chain, but not find it.
You can reference it by
theObject.doThis();
However, more readable might be if you define your function like this:
function getMyObject() {
function doThis() {};
function doThat() {};
var theObject = {
doThis: doThis,
doThat: doThat,
combinations: {
doThisTwice: function () { doThis(); doThis(); },
doThatTwice: function () { doThat(); doThat(); }
}
};
return theObject;
}
But in this case, whenever you change doThis from the outside, doThisTwice will still reference the original function.
In doThisTwice, use theObject.doThis(); instead of doThis();
I know how to access the below member function when it's written like this:
var blady_blah=
{
some_member_function: function ()
{
}
}
I access it from outside doing blady_blah.some_member_function()
But how do I access the member function when it's written like this:
(function() {
some_member_function: function ()
{
}
})();
Braces, { }, are used to define both object literals and function bodies. The difference is:
var name = {}; // Object literal
Which you may also see written as
var name = {
};
That's just the same but with some space in between so it's still an object literal, and unfortunately it looks very similar to:
var name = function () { // Function body
};
An object can have members:
var name = {
member: "string"
};
Whereas a function cannot; a function has statements:
var name = function () {
do_something();
var result = do_something_else();
};
You can't write
var name = function () {
member: "string"
};
Because you've mixed the two uses of { } together.
A variable can be defined within a function, but it can't be seen outside the function - it's within the function scope:
var name = function () {
var something_useful = string;
};
The second example is a closure (it just happens to have a syntax error inside). Minus the bad syntax, your self-evaluating anonymous function looks like this:
(function() {
})();
If you'd like, you can define functions inside this that will be invisible to the outside world. This is useful if you're interested in maintaining a clean global namespace, for example with library code.
(function() {
function utilityFunctionFoo() {
}
function utilityFunctionBar() {
}
})();
Of course, if you'd like to call any of these functions from the outside world, you're out of luck. Or are you? Actually, there's another way to define a function:
var foo = function() {
}
That's exactly the same as writing:
function foo() {
}
...Except that when written in the second style, you can actually omit the var keyword and create a global variable! Bringing it all together:
(function() {
publicData = "stuff accessible from outside anonymous function";
var privateData = "stuff that stays inside anonymous function";
function utilityFunctionFoo() {
}
function utilityFunctionBar() {
}
usefulFunctionExport = function() {
utilityFunctionFoo();
utilityFunctionBar();
}
})();
usefulFunctionExport();
You can't access it after the function it's in terminates. It's a local variable that goes out of scope when its parent function ends.
You should make the main function be a constructor so that it returns a new instance of a class (you could name it Blahdy_blah) with the member function as one of its properties.
Look up constructors, their return values, and accessing member variables.
If you want to execute the function you need to return an object that exposes the function.
var LIB = (function() {
var fn = {
member_function : function(){}
};
return fn;
})();
and to call
LIB.member_function();
(function() {
blady_blah.some_member_function();
})();
If you need to add stuff into it you would write it like this.
(function() {
blady_blah.some_member_function(function(){
// Do stuff...
});
})();
I have the following function
var myInstance = (function() {
var privateVar = 'Test';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accesible here
alert(privateVar);
},
publicMethod2: function () {
}
};
})();
what's the difference if I add a new to the function. From firebug, it seems two objects are the same. And as I understand, both should enforce the singleton pattern.
var myInstance = new (function() {
var privateVar = 'Test';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accesible here
alert(privateVar);
},
publicMethod2: function () {
}
};
})();
While the end result seems identical, how it got there and what it executed in is different.
The first version executes the anonymous function with this being in the context of the window object. The second version executes the anonymous function, but this is in the context of a new empty object.
In the end, they both return another object(your Singleton). It's just a slight difference in execution context.
To test this out, but an alert(this); right before the declaration of the privateVar variable.
#Tom Squires: That's not necessarily true and is poor practice not to declare your variables. A script with the "use strict"; directive does cause the JS engine to complain (assuming that the engine supports "use strict";