Typescript generating redundant variable - javascript

Consider the following Typescript code:
module demoAppModule{
'use strict';
export module nest{
export var hello = function () {
alert('Hello!');
};
}
}
demoAppModule.nest.hello();
After transpiling we have the following javascript code:
var demoAppModule;
(function (demoAppModule) {
'use strict';
(function (nest) {
nest.hello = function () {
alert('Hello!');
};
})(demoAppModule.nest || (demoAppModule.nest = {}));
var nest = demoAppModule.nest;
})(demoAppModule || (demoAppModule = {}));
demoAppModule.nest.hello();
Why is this line generated? It hurts my eyes.
var nest = demoAppModule.nest;

Short Answer: Its needed to access the module variable locally. E.g.
module demoAppModule{
'use strict';
export module nest{
export var hello = function () {
alert('Hello!');
};
}
// The following would not be possible without that line
console.log(nest.hello);
}
demoAppModule.nest.hello();
Longer Answer: Its similar to the var added before a module e.g. notice var x:
// TypeScript
module x{export var foo;}
// Generated JavaScript
var x;
(function (x) {
x.foo;
})(x || (x = {}));
But when you are inside a module + export a module the var needs to be added to outermodule.innermodule so you do not do var innermodule upfront. You add it to outermodule and then create a local variable to point to the innermodule which you can see in the generated javascript:
// Notice var here
var demoAppModule;
(function (demoAppModule) {
'use strict';
// Notice no var here
(function (nest) {
nest.hello = function () {
alert('Hello!');
};
})(demoAppModule.nest || (demoAppModule.nest = {}));
// Notice var assinged afterwards
var nest = demoAppModule.nest;
// The following would not be possible without that line
console.log(nest.hello);
})(demoAppModule || (demoAppModule = {}));
demoAppModule.nest.hello();

Related

Expose legacy revealing module pattern methods and variables using Webpack

I'm trying to hotwire webpack to use some legacy code but this arrangement:
slidesystem.js:
export var slideSystem = (function () {
var position = 0;
function init() {
alert('winner!');
} // init
})();
app.js
import {slideSystem} from './slidesystem';
slideSystem.init();
alert(slideSystem.position);
Isn't working as expected... Is there a better way to do this?
Here's one way to do it using the demo above:
slidesystem.js
const slideSystem = (function () {
'use strict';
var position = 0;
function init() {
alert('winner!');
} // init
return {
init: init,
pos: pos
};
})();
export default slideSystem;
app.js
import {slideSystem} from './slidesystem';
slideSystem.init();
alert(slideSystem.position);

Pass variables to another module

I have a few modules that access common HTML elements. I was thinking of making a module to create variables for each element to avoid constantly accessing the DOM tree but not sure how to do it.
So...
var Handles = (function(){
var $ag= $('.ui.dropdown.age_group');
// ... more like above
}());
var SomeModule= (function(){
console.log($ag); // Can I access $ag here somehow?
}());
You can make ag global
var ag;
var Handles = (function(){
ag = 5;
}());
var SomeModule= (function(){
console.log(ag);
}());
Not sure if this is what you are looking for, but another option is to call SomeModule as a function
var Handles = (function() {
var ag = 6;
SomeModule(ag);
}());
function SomeModule(x) {
console.log(x);
}
If you would you can return it as an object from Handles.
var Handles = (function() {
var $ag = ['Element'];
return {
$ag: $ag
};
}());
var SomeModule = (function() {
console.log(Handles.$ag);
}());
This is an option, but you can doing this with other forms.
var Handles = (function(){
var $ag= $('.ui.dropdown.age_group');
// ... more like above
}());
var SomeModule= (function(){
console.log(Handles.$ag); // Can I access $ag here somehow?
}());
Also can create a other module to share variables!
var shared = (function () {
var variable1 = 1;
})();
var module1 = (function (shared) {})(shared);

Understanding module design pattern in javascript

I am not very good in JavaScript. so when I saw a block of code now then many area is not clear. So someone please help me to understand.
I know this below way people declare their module
var Module = (function () {
var privateMethod = function () {
//A Private Method
var privatemember; // scope is only private method
};
return {
publicMethod: function () {
//you can call private method here.
}
};
})();
Module.publicMethod(); //works
Just I saw another bit different code for module pattern as follows where knockout.js is used.
var HMS = HMS || {};
$(function () {
HMS.PatientModel = function () {
this.Patient_Name = ko.observable();
this.Patient_Address = ko.observable();
};
HMS.PatientViewModel = function () {
var patient = ko.observable(),
loadPatient = function () {
var newModel = new HMS.PatientModel();
newModel.Patient_Name("Premkumar");
patient(newModel);
};
return {
patient: patient,
loadPatient: loadPatient
};
} ();
HMS.PatientViewModel.loadPatient();
ko.applyBindings(HMS.PatientViewModel);
});
1) What is this code var HMS = HMS || {}; ?
2) See this $(function () {}) ();
Why module has no name specific. see my first code where I give a name to my module like this way var Module = (function () {}) ()
3) Inside module code every function name has started with HMS.............why like HMS.PatientModel = function () { };
Please help me to understand the second set code point wise. Thanks
var HMS = HMS || {};
that expression defines the var HMS to HMS or empty object if it is not defined is a short hand for
if(HMS) {
var HMS = HMS;
} else {
var HMS = {};
}
2) You are creating an object from an IIFE
They are declaring and empty object if it does not exist, and decorating it with the methods/functions once the function below its executed.
is the same as this:
var HMS = {
PatientModel : function () {},
PatientViewModel : function () {},
}
3) And that is why they use HMS inside the function.
var HMS = {};
HMS.PatientModel = function() {};
HMS.PatientViewModel = function() {};
You should read about Closures, IIFE, and How to “properly” create a custom object in JavaScript?
Sample and short explanation of closure:
A closure is when you have access to variables that are not in the lexical scope of the function For example, a function declared inside another function, will have access to the parent variables.
eg:
(function(){
var a = 1;
function mainFunction() {
function innerFunction() {
var b = 2
function subFunction() {
console.log(a); //We have access to "a" here.
console.log(b); //We have access to "b" here.
}
subFunction();
}
innerFunction();
console.log(a); //We have access to "a" here.
console.log(b); //We dont have access to "b" here. //error
}
mainFunction();
})();
console.log(a); //We dont have access to "a" here. //error
1) what is this code var HMS = HMS || {}; ?
If HMS is undefined HMS is to be equal to an empty object otherwise use HMS as is (in your case HMS is an object).
2) see this $(function () {}) ();
It's called IIFE.
3) why like HMS.PatientModel = function () { };
HMS is an object and just adding its property with value. Value may be anything.
4) From your comment in another answer, why they didn't define module name?
They have defined the module name as Module. See var Module = (function(){}());

Typescript idiom to prevent duplicate modules included in a page

Suppose I have a TypeScript module defined like:
module Foo {
export var now = new Date();
}
This gets transpiled to:
var Foo;
(function (Foo) {
Foo.now = new Date();
})(Foo || (Foo = {}));
If I were writing in pure JavaScript, I would have included something like:
var Foo;
(function (Foo) {
if (window.Foo) return; // <-- PREVENT DUPLICATES!
Foo.now = new Date();
})(Foo || (Foo = {}));
to ensure that this module gets defined only once even if the <script/> gets included multiple times in a page. How do I achieve the same effect in TypeScript?
If you are writing your whole program in TypeScript, the compiler checks this for you...
module Foo {
export class X {
go() {
alert('First');
}
}
}
module Foo {
export class X { // Duplicate identifier X
go() {
alert('Second');
}
}
}
If you can, using external modules along with a module loader (RequireJS for example) ensures that non of your code needs to be added to the global scope, so it wouldn't conflict...
import foo = require('./foo');
export class Y {
go() {
return new foo.X();
}
}
Compiles to:
define(["require", "exports", './foo'], function(require, exports, foo) {
var Y = (function () {
function Y() {
}
Y.prototype.go = function () {
return new foo.X();
};
return Y;
})();
exports.Y = Y;
});
From this discussion on TS forums, I was able to come up with the following solution:
module window {
if (window.Foo) return;
export module Foo {
export var now = new Date()
}
}
This compiles to:
var window;
(function (window) {
if (window.Foo)
return;
(function (Foo) {
Foo.now = new Date();
})(window.Foo || (window.Foo = {}));
var Foo = window.Foo;
})(window || (window = {}));

logging javascript module names

I want to be able to log my module initializations to see what happens. Is there a way to get the module namespace and log it to the console.
(function($, bis, window, document, undefined) {
"use strict";
//other app code
bis.library = bis.library || function(module) {
$(function() {
if (module.init) {
module.init();
//how can I make it log the module namespace
console.log('module' + module.toString() + 'initialized');
}
});
return module;
};
//other app code
})(jQuery, window._bis = window._bis || {}, window, document);
example of my module definition
(function($, bis, window, document, undefined) {
"use strict";
var common = bis.common,
urls = bis.urls,
defaults = bis.defaults,
createWorklist = bis.createWorklist,
editWorklist = bis.editWorklist,
editMoveBoxesWorklist = bis.editMoveBoxesWorklist;
bis.worklist = bis.worklist || bis.library((function() {
// module variables
var init = function() {
//module init code
};
//other module code
return {
init: init
};
})());
})(jQuery, window._bis = window._bis || {}, window, document);​
So I want the line console.log to log the following text "module bis.worklist initialized" for example.
I did as Pointy suggested. I have added a name property to my modules and just use the
console.log(module.name);

Categories

Resources