How would I do something along these line? Do I need to use new Function()?
var bunchOfFunctionNames = ["functions", "of", "functions"];
for (var i = 0; i < eventTypes.length; i++) {
myObject.prototype[bunchOfFunctionNames[i]] = function() {
// do some stuff
};
};
In re: my comment about getting at the value of "i" in your function creation loop, the problem is going to be that "i" will be shared by all the functions. In other words, there's just one "i" variable in the outer function (where the loop is), so if you reference "i" in the functions you're creating, well, it won't work out properly (probably). All of them will see "i" as being the "length" of your array of names, because that's what it'll be at the end of the loop.
There are several ways to deal with that. If you were a Scheme programmer at heart, you'd do this:
for (var i = 0; i < eventTypes.length; i++) {
myObject.prototype[bunchOfFunctionNames[i]] = (function(copy_of_i) {
return function() {
// do some stuff, merrily referencing "copy_of_i"
}
})(i);
};
That "anonymous" function inside the loop provides a new scope, so because "i" is passed in as a parameter (called "copy_of_i", even though I hate underscores in variable names), it's safe for the real function to use it. The anonymous function returns the real function, so that's the function that ends up in the object prototype.
Another option would be to pull that anonymous function out of the loop:
function makeFunctionForName(i) {
return function() {
// do something, and now "i" is the parameter and "safe"
};
}
for (var i = 0; i < eventTypes.length; i++) {
myObject.prototype[bunchOfFunctionNames[i]] = makeFunctionForName(i);
}
Related
http://jsfiddle.net/ujapned5/
I'm trying to make an "initializer" function that will be used to define CSS id and class names.
function init() {
//our empty array for pushing
var DivNamingPushArray = [];
//object where we define our properties that will be used later
var namingScheme = {
"parentId": {
"firstChild": "blah",
"secondChild": "blahblah",
"thirdChild": "blahblahblah"
}
}
//loop through the namingScheme object and push into array
for (propOne in namingScheme) {
DivNamingPushArray.push(propOne);
for (propTwo in namingScheme[propOne]) {
DivNamingPushArray.push(namingScheme[propOne][propTwo])
}
}
}
function execute() {
//call the "init" function
init();
//this cannot be called
console.log(DivNamingPushArray);
//however, why can this be successfully called?
console.log(propOne);
}
execute();
I would really prefer to keep these functions separate, instead of including execute inside init. There are other functions that will need to call the DivNamingPushArray variable later on.
I am looking through the MDN documentation on variable scope but not finding a simple solution...
I'd suggest you use a third function to separate your logic
As for the propOne, you can see my comment in your question, just put var in front of it.
Working example here
execute();
function init(app) {
app.DivNamingPushArray = getNamingArray();
}
function execute() {
var app = {};
//call the "init" function
init(app);
console.log(app.DivNamingPushArray);
}
function getNamingArray() {
//our empty array for pushing
var DivNamingPushArray = [];
//object where we define our properties that will be used later
var namingScheme = {
"parentId": {
"firstChild": "blah",
"secondChild": "blahblah",
"thirdChild": "blahblahblah"
}
}
//loop through the namingScheme object and push into array
for (var propOne in namingScheme) {
DivNamingPushArray.push(propOne);
for (var propTwo in namingScheme[propOne]) {
DivNamingPushArray.push(namingScheme[propOne][propTwo])
}
}
return DivNamingPushArray;
}
I suggest to use some js pattern like module to separate it:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript
and the using something like observer to let function comunicate.
This is not a simple implementing solution, but you can have fun with it!
If you want DivNamingPushArray accessible within the scope of execute(), take its declaration one level upper, before init() declaration :
//Declare your array outside of your init function
var DivNamingPushArray = [];
function init() {
//...
For propOne, see Amit Joki's answer.
When you declare a variable without the keyword var, it becomes global. Add var before you declare the variables in for...in loop.
for (var propOne in namingScheme) {
DivNamingPushArray.push(propOne);
for (var propTwo in namingScheme[propOne]) {
DivNamingPushArray.push(namingScheme[propOne][propTwo])
}
}
When a variable becomes global, or part of window, it can be accessed anywhere. So, always use var to keep the variables in scope and thereby avoiding the pollution of global scope.
After you've called init, propOne and propTwo have become global variables and therefore can be accessed anywhere. As to DivNamingPushArray, declare it one-level higher, so it will be visible to other functions or try to use module pattern.
Javascript variable scoping works like this:
//this will not be changed in "init" function.
DivNamingPushArray = [];
//this will be changed because you don't localize your variable in init function
propone = 'value';
function init() {
//this "var" declaration localizes the variable.
//You can do anything you want with it and
//the global DivNamingPushArray wont change.
//The only way to use the global variable now is through
//the global object. (window.DivNamingPushArray for browsers)
var DivNamingPushArray = [];
// if you would have used "for (var propOne in namingScheme)",
// the variable would have been local
for (propOne in namingScheme) {
// ...
}
}
This is my code:
function func(){
for(i=0; i < 5; i++){
alert('g');
}
}
for(i=0; i < 5; i++){
func();
alert('h');
}
What I expected was: gggghgggghgggghgggghggggh
but what received was just ggggh
I found out that's because there is function scope, not block scope in JS. What I'd like to know is how to preserve such a behavior. I mean to force something like block scope. Otherwise it's very easy to make really nasty bugs - e.g. while using a function somebody else wrote or the one you wrote yourself, but a few months earlier.
This actually doesn't have to do with function vs. block scope - it has to do with implicit global variables.
The short story: You are accidentally creating a global variable in your for loop - if you use for(var i=0; rather than for(i=0; you'll get the expected results.
The slightly longer version:
alert("typeof i: " + typeof i);
// Alerts "typeof i: undefined"
function func() {
// References the *global* variable `i`
for(i=0; i < 5; i++){
alert('g');
}
}
// Creates a *global* variable `i` and sets it to 0
for(i=0; i < 5; i++) {
alert("i at start of iteration: " + i);
// Alerts "i at start of iteration: 0"
func();
// `func` has just altered *global* state - here's the proof
alert("i after call to func: " + i);
// Alerts "i at start of iteration: 5"
alert('h');
}
alert("typeof i: " + typeof i);
// Alerts "typeof i: number
// `i` is now in the global scope.
// Left as an exercise for the reader:
// try it again with `var i=0;` in both of the `for` loops.
Issue with variable i's scope.
function func(){
for(var i=0; i < 5; i++){
alert('g');
}
}
for(var i=0; i < 5; i++){
func();
alert('h');
}
Try declaring i as a local variable in your function:
function func(){
var i;
for(i=0; i < 5; i++){
alert('g');
}
}
As already stated in other answers, your code doesn't work because you don't declare the i variable with var, which automatically makes it global. So not really a function versus block scope issue. If you use var to declare your variable(s) then the scope of the variable(s) will be limited to the same function where the declaration is including within any nested functions, or global if not in a function.
If you use the same variable name in nested functions then the one in the inner scope is said to "shadow" the outer one; the inner function can't access the outer function's variable of that name in that case since using that name will only give it its own variable. So to speak. Though you can access global variables by treating them as properties of the window object.
"What I'd like to know is how to preserve such a behavior. I mean to force something like block scope. Otherwise it's very easy to make really nasty bugs..."
Well no, once you start using var correctly it isn't difficult to avoid those bugs. But you can force block scope by introducing an immediately invoked anonymous function:
(function() {
// variables created in this function are accessible
// only within this function
var x, y, z;
})();
console.log(typeof x); // "undefined" (x can't be seen from outside the function)
The parentheses around function(){} are required so that the function is interpreted as an expression and not a function statement; the extra () at the end is to cause that function expression to be executed immediately. A common use for this structure is to enclose an entire script in it so that no variables or functions in it become global and thus don't interact with other scripts loaded from other JS include files. (You can have pseudo-global variables within the block shared between several functions also declared within the block.)
So for example if you wanted to make the body of a for statement into a "block" with scope you could do this:
for (var i = 0; i < something; i++) {
(function() {
var x = i;
// do something with x
})();
}
function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
var ctr = getCtr();
ctr();
ctr();
I've been using Javascript from last five years, but this question made me dumb in last interview. I tried everything to my knowledge but can't figure it out.
Can you please help me with the output and reason for it so that I can be better equipped for future interviews if I have one.
var ctr = getCtr();
This calls getCtr(), which initializes i to 0, and stores a reference to the function
function() {
console.log(++i)
}
in ctr. Because that function was created in the scope of getCtr(), the variable i is still accessible in the scope of the function stored in ctr.
The first call to
ctr()
executes console.log(++i) which has a preincrement on i, so it prints out 1. The second call executes the same code, with the same preincrement, and prints out 2.
DISCLAIMER: Not a javascript developer. Forgive me if I've made an error or used some unpreferred wording.
So the code you posted outputs 1 2. Yet the code:
function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
getCtr()();
getCtr()();
outputs only 1 1!
The difference is that if you save a reference to getCtr() by using the var ctr = getCtr();, you create what is called a closure.
So the difference between calling getCtr()() and ctr() is that ctr has i defined in its scope, and that scope is saved thanks to var ctr = getCtr();. Because the reference is saved, the function inside of ctr is able to always act on the same variable.
run this:
var m=0;
var d=0;
alert(m++ +":"+ ++d);
and you get "0:1"
IF it were me asking in an interview, the difference in where the ++ is is what I would be after :)
http://jsfiddle.net/MarkSchultheiss/S5nJk/
Closures
The return statement in that function saves i. So when var i = 0; is only called var ctr = getCtr();. Then ctr becomes the returned function:
function () {
console.log(++i)
}
and the variable ctr has i in the scope of the outer function, getCtr() and the return function is in the scope of getCtr() as well.
okay, getCtr is a function that returns an other function.
It also contains a var called "i" which is set to 0.
"i" is also available in the scope of the returned function.
the preincrement of "i" before logging it to the console causes that it increases by 1 every time the returned function, which is stored in "ctr", is called.
When executed, function getCtr returns an inner anonymous function.
This function is now referenced by variable ctr
Because the anonymous function was created inside getCtr it will have access to getCtr private scope object, which contains variable 'i'. This is known as a closure.
var ctr = getCtr()
Every time the anonymous function is executed it pre-increments i, and writes in in the console.
ctr()
Lets break it down using terms you might know from classical inheritance based OOP languages:
// In javascript functions are first-class objects
// This function is being used like a class would be in Java
function getCtr(){
// You can think of this as a private variable of the getCtr "class"
var i = 0;
// Because it is returned, this is effectively a public method of getCtr
return function(){
// Which increments i and then prints it.
console.log(++i);
}
}
// This makes the variable ctrl an instance of getCtr.
var ctr = getCtr();
// This calls ctr's only public method.
ctr();
ctr();
So the output would be "1, 2".
What this question is meant to do is test if you understand Javascript's prototypal inheritance, ability to have anonymous functions, and closures.
A clarified version of that could that would do the same thing would be:
var myProtoype = function() {
var privateVariable = 0;
var privateMethod = function () {
privateVariable++;
console.log(privateVariable);
}
return {
publicMethod: privateMethod
};
}
var myInstance = new myPrototype();
myInstance.publicMethod();
myInstance.publicMethod();
That function is a Javascript Module. You can have a good reading about it on Javascript: the Good Parts, which is a great book and I highly recommend. A Module uses Javascript closures to create private variables and if assigned to a var the var will retain it's vars each time it's called instead of redefining the vars.
A module works like this
function moduleName(privateVar1){
var privateVar1;
var privateVar2;
return {
exposedFunction1: function (var1) {
// Do stuff... using private vars
return something;
},
exposedFunction2: function (var1, var2) {
// Do stuff...
return something;
}
}
}
var moduleInstance = moduleName(privateVar1);
moduleInstance.exposedFunction(var1);
I'm reading this article
and there is a paragraph:
If you ever find yourself needing to explicitly scope a variable
inside a function you can use an anonymous function to do this. You
can actually create an anonymous function and then execute it straight
away and all the variables inside will be scoped to the anonymous
function:
(function() {
var myProperty = "hello world";
alert(myProperty);
})();
alert(typeof(myProperty)); // undefined
I met with this already but still need some clarification why should I need to explicitly scope a variable inside a function when variables are implicitly scoped inside a function in Javascript.
Could you explain the purpose of this?
thank you
for (var i = 0; i < 10; i++) {
setTimeout(function() { console.log(i) }, 10);
}
// alerts 10, 10 times
for (var i = 0; i < 10; i++) {
(function(i) {
// explicitly scope i
setTimout(function() { console.log(i) }, 10);
})(i);
}
When generating functions inside other functions and accessing variables up the scope chain through closure scope it may be useful to "explicitly scope" a variable inside the outer function.
Although this is an anti pattern. The correct solution would be
var generateLogger = function(i) {
return function() { console.log(i); };
}
for (var i = 0; i < 10; i++) {
setTimeout(generateLogger(i), 10);
}
Since generating functions in a loop is inefficient and bad practice.
There are no real use cases of "explicitly scoping" variables that can't be avoided by not creating functions inside other functions.
Here's some JavaScript:
linkElem.click(function () {
var data = linkElem.data();
alert(''+data.mls + ' ' + data.id);
});
It works.
linkElem is a local variable that I create in a loop inside a function. I assign some data to it with jQuery's .data(). If I did not call .click(), linkElem would be reassigned during the loop and then recycled after the function returns. However, I have created an anonymous function which references linkElem. So I am no longer sure what is going on.
My guess is that all of the anonymous functions and linkElems created during the loop are given UIDs of some kind and moved to persistent/global scope. Is this correct? Gratuitous detail would be much appreciated.
Yes, your description is pretty close. The local storage for a Javascript function call is just a block of memory allocated for local variables. If you "capture" that by creating another function inside a called function, then the storage is retained and the local variables carry on with their lives, unaware that the function that gave them birth might be long dead.
It's important to keep in mind that only functions create such storage — things like brace-enclosed loop bodies are not separate storage areas. Thus a common error is to declare a variable in a function and re-use it among several functions created in a loop. That's not inherently wrong, but the effect can be surprising:
function whatever() {
for (var i = 0; i < 3; ++i) {
setTimeout(function() { alert(i); }, 5000);
}
}
If you run that, you'll see three alerts that all say "3". Why? Because they all share the same "i" variable. You can avoid that by introducing another function layer:
function whatever() {
for (var i = 0; i < 3; ++i) {
setTimeout((function(private_i) { return function() { alert(private_i); }; })(i), 5000);
}
}
The "wrapper" function is just there to provide a local variable (the parameter "private_i") whereto the loop variable "i" can be copied.
However, I have created an anonymous function which references linkElem. So I am no longer sure what is going on.
It still gets reassigned, unless you are wrapping it in another level of scope (NB: another function).
Consider the following:
for (var j = 0;j < 10;j += 1) {
arrayOfLinks[j].onclick = function () {
alert(j);
};
}
In this case, all of those links would alert 10 when clicked, because j is outside of the scope and is being updated.
If you're creating linkElem in the same way, you are likely to only get the result of the last linkElem in the loop.
This is a better way:
linkElem.click(function () {
var data = $(this).data(); // no longer dependent on `linkElem` reference
alert(''+data.mls + ' ' + data.id);
});
Please refer to this How do JavaScript closures work?
This may help you understanding closures.
Whenever you see the function keyword within another function, the inner function has access to variables in the outer function.
function foo(x) {
var tmp = 3;
function bar(y) {
alert(x + y + (++tmp));
}
bar(10);
}
foo(2)
This will always alert 16, because bar can access the x which was defined as an argument to foo, and it can also access tmp from foo.
That is a closure. A function doesn't have to return in order to be called a closure. Simply accessing variables outside of your immediate lexical scope creates a closure.
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp));
}
}
var bar = foo(2); // bar is now a closure.
bar(10);
The above function will also alert 16, because bar can still refer to x and tmp, even though it is no longer directly inside the scope.
However, since tmp is still hanging around inside bar's closure, it is also being incremented. It will be incremented each time you call bar.
The simplest example of a closure is this:
var a = 10;
function test() {
console.log(a); // will output 10
console.log(b); // will output 6
}
var b = 6;
test();
When a Javascript function is invoked, a new execution context is created. Together with the function arguments and the parent object, this execution context also receives all the variables declared outside of it (in the above example, both 'a' and 'b').
It is possible to create more than one closure function, either by returning a list of them or by setting them to global variables. All of these will refer to the same x and the same tmp, they don't make their own copies.
[you]: Fascinating, tell me more!
Here the number x is a literal number. As with other literals in JavaScript, when foo is called, the number x is copied into foo as its argument x.
On the other hand, JavaScript always uses references when dealing with Objects. If say, you called foo with an Object, the closure it returns will reference that original Object!
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + tmp);
x.memb = x.memb ? x.memb + 1 : 1;
alert(x.memb);
}
}
var age = new Number(2);
var bar = foo(age); // bar is now a closure referencing age.
bar(10);
As expected, each call to bar(10) will increment x.memb. What might not be expected, is that x is simply referring to the same object as the age variable! After a couple of calls to bar, age.memb will be 2! This referencing is the basis for memory leaks with HTML objects.