Javascript varibles across functions - javascript

As an exercise, I'm writing my code within the same namespace (namespace being sample):
if ("undefined" == typeof(sample)) {
var sample = {};
}
sample = {
foo : function () {
},
bar : function () {
}
};
How do I create a variable within the same namespace which is accessible by all functions?

I assume you're trying to access a variable inside the sample namespace. To do this, you declare the variable at the same level as your functions, and from within the functions, you access it using the keyword this
sample = {
myVar:10; // this is your variable
foo : function () {
return this.myVar++; // use this keyword to access it.
},
bar : function () {
}
};
Note: If you're creating a function (closure) inside your function, you'll want to create an alias for the this keyword (like _self) so that the context isn't overridden inside your new function.

Another alternative:
(function(){
//Constructor
function Sample(name) {
this.sampleName = name;
}
Sample.prototype = {
foo: function() {
this.sampleName = "otherSample";
},
bar: function() {
this.sampleName += "anotherSample";
}
};
var sample = new Sample("wow");
})();

Related

How to pass function scope (not context)?

Can you please help me to find the error in the code? I need to pass one method's scope to another method.
var obj = {
doIt: function() {
var a = 10;
this.doThat.call(this);
},
doThat: function() {
console.log(a);
}
};
obj.doIt();
If you want to access a in the scope of context, you can try this.
var obj = {
doIt: function() {
this.a = 10;
this.doThat.call(this);
},
doThat: function() {
console.log(this.a);
}
};
obj.doIt();
You do pass the "context" (aka this) around. a however, is not part of the current context, but of the current scope. So you either move a into the context:
var obj = {
doIt: function() {
this.a = 10;
this.doThat();
},
doThat: function() {
console.log(this.a);
}
};
Or you directly pass the value of a into doThat:
//...
this.doThat(a);
doThat(a) { /*...*/ }
You need to understand that there is difference between context and scope. scope is going to be something which will dictate which variables are accessible from a particular site whereas context is what will be the value of this at particular site or inside a function.
so if you want to use value of a in function doThat you need to bind value of a with this which is context in function doIt like: this.a = 10; and then access it using console.log(this.a) inside function doThat

I want to call parent function into function which is wraped in object

Below is my code -
contactNumberMask: function(value) {
return value
},
componentDidMount: function() {
this.params = {
cellNumber: ''
};
var maskList = $.masksSort($.masksLoad("http://cdn.rawgit.com/andr-04/inputmask-multi/master/data/phone-codes.json"), ['#'], /[0-9]|#/, "mask");
this.maskOpts = {
inputmask: {
onMaskChange: function(maskObj, determined) {
if (determined) {
var number = this.contactNumberMask(maskObj.mask);
this.params.cellNumber = number+'-'+this.params.cellNumber;
}
}
};
},
In this i want to call this.contactNumberMask() function inside onMaskChange() function. but it is not getting reference of this.
Use bind() to set the context
onMaskChange: function(maskObj, determined) {
if (determined) {
var number = this.contactNumberMask(maskObj.mask);
this.params.cellNumber = number+'-'+this.params.cellNumber;
}.bind(this)
There's some ways to do. For example, storing the this reference in a variable.
contactNumberMask: function(value) {},
componentDidMount: function() {
var that = this;
this.params = {
cellNumber: ''
};
var maskList = $.masksSort($.masksLoad("http://cdn.rawgit.com/andr-04/inputmask-multi/master/data/phone-codes.json"), ['#'], /[0-9]|#/, "mask");
this.maskOpts = {
inputmask: {
onMaskChange: function(maskObj, determined) {
if (determined) {
var number = that.contactNumberMask(maskObj.mask);
this.params.cellNumber = number+'-'+this.params.cellNumber;
}
}
};
},
You have several choices :
create a variable self at the beginning of componentDidMount function
var self = this
Then you use self instead of this.
you can also create a function _onMaskChange and then use the bind method to set the 'this' in this method
onMaskChange: _onMaskChange.bind(this, maskObj, determined)
Your function(maskObj, determined) block won't have the same context (this) as the surrounding block. That's because - if not specified other - a function block will create its own context (this). The function is not bound to the outer context.
Multiple answers above are an option. But what I would recommend is using the => arrow function syntax. This will implicitly bind() your function to the outer context:
onMaskChange: (maskObj, determined) => {...}
Also it has a much cleaner syntax.

Javascript singleton: How to access private variables?

I have this singleton. The public functions allow to set private variables but I am not able to set them in the way that I am able to use them in the private methods:
var ServiceInterface = (function () {
// Instance stores a reference to the Singleton
var instance;
function init() {
// Singleton
// Private methods and variables
var m_action;
function performAction() {
alert(m_action);
}
return {
// Public methods and variables
callBackend: function (sAction) {
m_action = sAction;
}
};
};
})
m_action is not available throughout the public and private section of the singleton. What am I doing wrong?
I think you're referring to this
var ServiceInterface = (function () {
var m_action;
function performAction() {
alert(m_action);
}
return {
// Public methods and variables
callBackend: function (sAction) {
m_action = sAction;
performAction();
}
};
})()
ServiceInterface.callBackend("Hello world");
You need to execute anonymous function. Running it enables to create variables and functions defined with the anonymous function and these cannot be seen outside. Most of js libraries use this convention to create modules and to avoid infecting the global scope
var ServiceInterface = (function () {
// code inside
})()
These are the variables and functions confined within the scope of anonymous function executed
// var ServiceInterface = (function () {
var m_action;
function performAction() {
alert(m_action);
}
// })()
Finally, return a javascript object that will expose functions that can be accessible outside the anonymous function scope
//var ServiceInterface = (function () {
// var m_action;
//
// function performAction() {
// alert(m_action);
// }
return {
// Public methods and variables
callBackend: function (sAction) {
m_action = sAction;
performAction();
}
};
//})()
However, why go through the trouble of making private variable and method for a singleton?
This is how you create a singleton with a private member variable.
ServiceInterface = new (function() {
var m_action = false;
this.setAction = function(s) {
m_action = s;
};
this.getAction = function() {
return m_action;
};
this.performAction = function() {
alert(ServiceInterface.getAction());
};
this.createCallback = function() {
return function(sAction) {
ServiceInterface.setAction(sAction);
};
}
})();
ServiceInterface.setAction("secret");
ServiceInterface.performAction();
ServiceInterface becomes a singleton because the constructor function is thrown away after it's created. ServiceInterface = new (.....)(); is how it's executed right after being declared. It's a singleton because there is no way for someone to create another instance.
I don't use var to create the instance. When you exclude var and you're not inside a function the new variable will be attached to the prototype of the parent object. In the browser this will be window. window is like a global singleton in javascript.
The local variable m_action is persisted because setAction and getAction reference it as closure functions, and the variable is attached to their scope. So they can be used as setter/getter methods.
You can now use ServiceInterface.setAction(sAction); in your callbacks to set the private member.
http://jsfiddle.net/thinkingmedia/w7DdE/6/

Is it possible to pass execution context of the immediately invoked function expression

Consider the following code:
(function() {
var a = 5;
var someFunc = function() { ... };
function anotherFunc() {
...
};
})();
window.myGlobalObj = {
init: function() {
// and somehow here I want to access to the IIFE context
}
};
I want to have the execution context of IIFE in my global object. I do have access to function expression and object itself so I can pass or modify something to make it work (and no, I can't rewrite everything inside the object or function).
Is it even possible?
The only way I see how that's poosible is by using eval to simulate dynamic scopes. Do this (note that the IIFE must be placed after the global object):
window.myGlobalObj = {
init: function() {
// and somehow here I want to access to the IIFE context
}
};
(function() {
var a = 5;
var someFunc = function() { ... };
function anotherFunc() {
...
};
eval("(" + String(window.myGlobalObj.init) + ")").call(window.myGlobalObj);
})();
Here's a reference as on how to use dynamic scopes: Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?
Edit: I've included an example to demonstrate the power of using dynamic scopes in JavaScript. You can play with the fiddle too.
var o = {
init: function () {
alert(a + b === this.x); // alerts true
},
x: 5
};
(function () {
var a = 2;
var b = 3;
eval("(" + String(o.init) + ")").call(o);
}());
The "contents" of your IIFE, i.e., a, someFunc, etc., are local to that function scope, so you can only access them within that scope. But you can assign window.myGlobalObj inside the IIFE:
(function() {
var a = 5;
var someFunc = function() { ... };
function anotherFunc() {
...
};
window.myGlobalObj = {
init: function() {
// and somehow here I want to access to the IIFE context
}
};
})();
Then the init function will have access to those variables since they are in its containing scope.
EDIT: if you can't move the definition of myGlobalObj into the IIFE the only thing I can think of is to use the IIFE to create a second global object that you access from myGlobalObj:
(function() {
var a = 5;
var someFunc = function() { ... };
function anotherFunc() {
...
};
// create a global object that reveals only the parts that you want
// to be public
window.mySecondObject = {
someFunc : someFunc,
anotherFunc : anotherFunc
};
})();
window.myGlobalObj = {
init: function() {
window.mySecondObject.someFunc();
}
};
No. It is not possible. The context you want to access is called closure and can be accessed only within the function (in your case, the anonymous function (IIFE how you call it)). For more about closures follow the excellent Douglas Crockfords The Javascript programming language video tutorial.
You will have to place those attributes to some shared object.

How can i call AnotherSubFunction using my obj

var obj = {
MainFunction: function() {
AnotherSubFunction: function() {
}
var variable = AnotherSubFunction ()
}
}
Can i do something like this...
How can i call AnotherSubFunction using my obj? Is it possible.
How to create a function inside another function...
The code in your question is not valid Javascript. You're probably looking for:
MainFunction: function() {
function AnotherSubFunction() {
// ...
}
var variable = AnotherSubFunction();
}
Or maybe:
MainFunction: function() {
AnotherSubFunction = function() {
// ...
}
var variable = AnotherSubFunction();
}
However, in both cases, the name AnotherSubFunction associated with the nested function only exists in the scope of the enclosing function (MainFunction) and will not be accessible directly from obj.

Categories