I came across this type function in an example code, and it looks widely used. But I cannot figure out how to call this, or infact, what pattern it represents.
l = function (a1){
someVar = {
someFn: function(a2){
console.log(a1);
console.log(a2);
}
}
}
How would i go about executing someFn? Does this have something to do with closures?
UPDATE:
This is how the code is being used. As #joseph-the-dreamer guessed, it is being used as part of a module, where:
App.module("Module", function(a1) {
someVar = {
someFn: function(a2){
console.log(a1);
console.log(a2);
}
}
})
From it's current state, you need to call l first to set someVar to access someFn. Otherwise, you can't access someFn at all.
But without any variable declaration of someVar, calling l will create an implied global someVar. Implied globals isn't a good practice. You should declare someVar somewhere, even if you mean it to be a global.
var someVar;
l = function (a1){
someVar = {
someFn: function(a2){
console.log(a1);
console.log(a2);
}
}
}
l(1);
someVar.someFn(2);
//1
//2
You can also return someVar from calling l to access someVar. Note that this time, someVar is a local variable in l.
var l = function (a1){
var someVar = {
someFn: function(a2){
console.log(a1);
console.log(a2);
}
}
return someVar;
}
l(1).someFn(2);
As for pattern, I think what you have there is an incomplete form of the module pattern. Usually, module pattern wraps things in an IIFE, and returns an object as an interface to the module.
If someVar is not a variable in a scope outside of l(), then you cannot call someFn(), since someFn() is a private member function of someVar.
Otherwise, if you do have access to someVar, then you can call someFn() like this someVar.someFn(). Note that in this case, the console.log(a1) will behave strangely since a1 is has been assigned only since the last time l() was called.
In JavaScript there are 2 types of variables: global and local.
//local
var foo = "foo";
//global
bar = "bar";
From what I see in your sample, l is a global variable that is used to store an anonymous function. Inside this function there is a global variable named someVar that stores an object that has a local variable named someFn that stores an anonymous function.
To execute someFn, you must do the following:
l("Foo"); //This does not output anything
someVar.someFn("Bar"); //This will output "Foo" and then "Bar"
When you call l("Foo");, you are creating the global variable someVar. This in turn means you can use someVar anywhere even outside of the scope of the anonymous function stored in l. You are using closures for the argument a1.
A global variable can be used anywhere and I humbly suggest to limit its usage as it will pollute the global scope which means that it is quite error prone.
An approach that does not use global variables would be better. Little example here:
"use strict";
var l = function(a1) { //constructor
var _a1 = a1; //private variable
this.someFn = function(a2) { //public method
console.log(_a1);
console.log(a2);
};
};
var object1 = new l("Foo");
var object2 = new l("Foo");
object1.someFn(1); //outputs "Foo" and then 1
object2.someFn(2); //outputs "Foo" and then 2
Related
I decided to create a funcB function that I call from funcA. I want all variables from funcA to be available in the funcB so func B can change that variables.
How to modify the code below so it meets my requirements? I doubt passing all variables it the only possible and the best way.
function funcB(){
alert(var1);//how to make it alert 5
alert(var20);//how to make it alert 50
}
function funcA(){
var var1=5;
...
var var20=50;
funcB();
}
var obj = {
one : "A",
two : "B",
fnA : function() {
this.fnB(); // without fnB method result will be displayed as A B, with fnB as C D
console.log(this.one + " " + this.two);
},
fnB : function() {
this.one = "C";
this.two = "D";
}
};
obj.fnA();
this keyword refers to obj object
You can define object with properties and methods inside it. With methods all the variables can be manipulated as you wish, from this example with fnB I'm changing values of properties which are displayed from fnA method
JSFiddle
One way is to drop the var keyword:
function funcB(){
alert(var1);//how to make it alert 5
alert(var20);//how to make it alert 50
}
function funcA(){
var1 = 5;
var20 = 50;
funcB();
}
This will expose them to the global scope so funcB can access them. Notice you can also create the varaibles in the global scope itself, with the var keyword, but both methods will ultimately have the same effect.
Note:
This may not work if there is already a var1 or var20 in the global scope. In such case, it will modify the global value and may result in unwanted errors.
This method is not preferred for official code, and is bad practice Reason
This is not possible as when you declare a variable with the var keyword, they are scoped to the function in which they are declared.
If you avoid the var keyword, they are instead defined as a global variable. This is deemed very bad practice.
I would recommend you read up on javascript coding patterns, particularly the module pattern.
For example:
var myNamespace = (function () {
var foo, bar;
return {
func1: function() {
foo = "baz";
console.log(foo);
},
func2: function (input) {
foo = input;
console.log(foo);
}
};
})();
Usage:
myNamespace.func1();
// "baz"
myNamespace.func2("hello");
// "hello"
I understand functions in 'js' have lexical scope (i.e. functions create their environment (scope) when they are defined not when they are executed.)
function f1() {
var a = 1;
f2();
}
function f2() {
return a;
}
f1(); // a is not defined
When I run just 'f()' it returns the inner function. Which I get, that's what 'return' does!
function f() {
var b = "barb";
return function() {
return b;
}
}
console.log(b); //ReferenceError: b is not defined
Why do you get 'ReferenceError: b is not defined?'
But doesn't the inner function above have access to it's space, f()'s space etc. Being that 'b' is being returned to the global space, wouldn't the console.log() work?
However when I assign 'f()' to a new variable and run it:
var x = f();
x();// "barb"
console.log(b); //ReferenceError: b is not defined
This returns 'b' which is "barb", but when you run console.log() again you'll get 'ReferenceError: 'b' is not defined'; Isn't 'b' in the global scope now since it has been returned? SO why didn't 'x()' also return the inner function just like 'f()' did?
You, my friend, are thoroughly confused. Your very first statement itself is wrong:
functions create their environment (scope) when they are defined not when they are executed
Actually it's the opposite. Defining a function doesn't create a scope. Calling a function creates a scope.
What's a scope?
To put it simply, a scope is the lifespan of a variable. You see, every variable is born, lives and dies. The beginning of a scope marks the time the variable is born and the end of the scope marks the time it dies.
In the beginning there's only one scope (called the program scope or the global scope). Variables created in this scope only die when the program ends. They are called global variables.
For example, consider this program:
const x = 10; // global variable x
{ // beginning of a scope
const x = 20; // local variable x
console.log(x); // 20
} // end of the scope
console.log(x); // 10
Here we created a global variable called x. Then we created a block scope. Inside this block scope we created a local variable x. Since local variables shadow global variables when we log x we get 20. Back in the global scope when we log x we get 10 (the local x is now dead).
Block Scopes and Function Scopes
Now there are two main types of scopes in programming - block scopes and function scopes.
The scope in the previous example was a block scope. It's just a block of code. Hence the name. Block scopes are immediately executed.
Function scopes on the other hand are templates of block scopes. As the name suggests a function scope belongs to a function. However, more precisely, it belongs to a function call. Function scopes do not exist until a function is called. For instance:
const x = 10;
function inc(x) {
console.log(x + 1);
}
inc(3); // 4
console.log(x); // 10
inc(7); // 8
As you can see every time you call a function a new scope is created. That's the reason you get the outputs 4, 10 and 8.
Originally, JavaScript only had function scopes. It didn't have block scopes. Hence if you wanted to create a block scope then you had to create a function and immediately execute it:
const x = 10; // global variable x
(function () { // beginning of a scope
const x = 20; // local variable x
console.log(x); // 20
}()); // end of the scope
console.log(x); // 10
This pattern is called an immediately invoked function expression (IIFE). Of course, nowadays we can create block scoped variables using const and let.
Lexical Scopes and Dynamic Scopes
Function scopes can again be of two types - lexical and dynamic. You see, in a function there are two types of variables:
Free variables
Bound variables
Variables declared inside a scope are bound to that scope. Variables not declared inside a scope are free. These free variables belong to some other scope, but which one?
Lexical Scope
In lexical scoping free variables must belong to a parent scope. For example:
function add(x) { // template of a new scope, x is bound in this scope
return function (y) { // template of a new scope, x is free, y is bound
return x + y; // x resolves to the parent scope
};
}
const add10 = add(10); // create a new scope for x and return a function
console.log(add10(20)); // create a new scope for y and return x + y
JavaScript, like most programming languages, has lexical scoping.
Dynamic Scope
In contrast to lexical scoping, in dynamic scoping free variables must belong to the calling scope (the scope of the calling function). For example (this is also not JS - it doesn't have dynamic scopes):
function add(y) { // template of a new scope, y is bound, x is free
return x + y; // x resolves to the calling scope
}
function add10(y) { // template of a new scope, bind y
var x = 10; // bind x
return add(y); // add x and y
}
print(add10(20)); // calling add10 creates a new scope (the calling scope)
// the x in add resolves to 10 because the x in add10 is 10
That's it. Simple right?
The Problem
The problem with your first program is that JavaScript doesn't have dynamic scoping. It only has lexical scoping. See the mistake?
function f1() {
var a = 1;
f2();
}
function f2() {
return a;
}
f1(); // a is not defined (obviously - f2 can't access the `a` inside f1)
Your second program is a very big mess:
function f() {
var b = "barb";
return function() {
return b;
}
}
console.log(b); //ReferenceError: b is not defined
Here are the mistakes:
You never called f. Hence the variable b is never created.
Even if you called f the variable b would be local to f.
This is what you need to do:
function f() {
const b = "barb";
return function() {
return b;
}
}
const x = f();
console.log(x());
When you call x it returns b. However that doesn't make b global. To make b global you need to do this:
function f() {
const b = "barb";
return function() {
return b;
}
}
const x = f();
const b = x();
console.log(b);
Hope this helped you understand about scopes and functions.
You get, "ReferenceError: b is not defined" because "b" is not defined where your console.log() call is. There's a "b" inside that function, but not outside. Your assertion that "b is being returned to the global space" is false.
When you invoke the function returned by your "f()" function, that will return a copy of the value referenced by that closure variable "b". In this case, "b" will always be that string, so the function returns that string. It does not result in the symbol "b" becoming a global variable.
But doesn't the inner function above have access to it's space, f()'s space etc.
Yes it has. It accesses the b variable and returns its value from the function.
Being that 'b' is being returned to the global space
No. Returning a value from a function is not "making a variable available in the caller scope". Calling the function (with f()) is an expression whose result is the value that the function returned (in your case, the unnamed function object). That value can then be assigned somewhere (to x), a property of it can be accessed or it can be discarded.
The variable b however stays private in the scope where it was declared. It is not [getting] defined in the scope where you call console.log, that's why you get an error.
What you want seems to be
var x = f();
var b = x(); // declare new variable b here, assign the returned value
console.log( b ); // logs "barb"
function f1() {
var a = 1;
f2();
}
function f2() {
return a;
}
f1(); // a is not defined
f2(); does not knows about the a,because you never passed 'a' to it,(That's Scope are
created when the functions are defined).Look function f2() would have been able to acess
a if it was defined inside f1();[Functions can access the variables in same scope in
which they are "DEFINED" and NOT "CALLED"]
function f() {
var b = "barb";
return function(){
return b;
}
}
console.log(b);
First of all You Need to Call f(); after executing f(); it would return another function
which needs to be executed. i.e
var a=f();
a();
it would result into "barb" ,In this case you are returning a function not the var b;
function f() {
var b = "barb";
return b;
};
console.log(f());
This would print barb on screen
I'm creating an object with multiple functions.. i.e.:
var test = {
setA: function(){
console.log(a)
}
endB: function(){
console.log(a)
}
}
How do I declare variable a so that it can only be accessed in the test object and every function within that the object? and is there anything unique about accessing it than other variables?
I know I can declare a global variable but would rather avoid doing that.
var test = (function() {
var a = 'test';
return {
setA: function(){ console.log(a) }, // <-- was missing a comma
endB: function(){ console.log(a) }
};
})();
This places a in a function invocation which creates a new variable environment. Only function inside this environment will be able to access it.
Your object that contains the functions is returned from the function, and assigned to test. Those two functions will continue to have access to a.
Example: http://jsfiddle.net/yWdFw/
This pattern:
(function() {
// your code
})();
...is commonly called an immediately invoked function expression or IIFE. You're defining a function, and invoking it immediately. As such, its return value is what's being assigned to test.
An alternative to patrick's answer is adding an attribute to the object and then accessing it via this
var test = {
a: 'blah',
setA: function(){
console.log(this.a)
},
endB: function(){
console.log(this.a)
}
}
This is what i am facing with
function AAA(){
this.f1 = function (){
/*expecting that f2 will be call as both of then are of same object.*/
console.log(f2(5));//
}
this.f2 = function(x){
return x;
}
}
x = new AAA();
x.f1(); //ReferenceError: f2 is not defined
Neither does it work,
function AAA(){
this.f1 = function (){
/*expecting that f2 will be call as both of then are of same object.*/
console.log(f3(5));//
}
/*naming the function f3 hope to get function reference, as function
on the right side has name now and in the closure of f1, right?*/
this.f2 = function f3(x){
return x;
}
function f4() {};
}
x = new AAA();
x.f1(); //ReferenceError: f3 is not defined
What is happening here? who are in closure of 'f1' except 'f4'? can't we call the same object function without 'this'?
You are not really using closures here. It will work fine if you change the line to
console.log(this.f2(5));
If you want to use closures, you can rewrite the class as follows:
function AAA()
{
var f1 = function()
{
console.log(f2(5));
};
// f2 is a private function.
var f2 = function(x)
{
return x;
};
// Define the public interface.
return { f1: f1 };
}
You’re confusing a few things here; this and closures are two completely different issues.
Your problem here is that you’re trying to refer to f2 directly, thereby assuming that this is part of the current execution scope. It isn't.
If you put f2 on this, you’ll have to keep referencing it as this.f2. To be able to reference f2 directly, you’ll have to declare a (separate) variable by that name, which you can then assign to this if you want, as qwertymk says.
Personally, I try to avoid this as much as I can, since its meaning is completely dependent on how the function is called (e.g. if AAA is called without specifying the new operator, this will refer to the global object!). It also saves you from headaches like the one above. Closures (as demonstrated by Elian) are a much better way of obtaining this functionality.
Interestingly enough, I've found I hardly ever need to use this.
In Elian's example, f2 is closed over: once the AAA function is done running, nobody can access f2, except the functions that were defined inside AAA (and are still accessible). In this case, the function f1 is accessible from the returned object, so that still exists. Therefore, f1 can still use f2.
That's what closures are about: a function can still access all the variables in its scope, even when those variables were declared in a function that's terminated.
It should be this.f2() not f2() by itself. You would use f2() if it was a private variable which means if it was created with a var keyword.
function AAA(){
var f3 = function(x) { return x; };
this.f1 = function (){
/*expecting that f2 will be call as both of then are of same object.*/
console.log(this.f2(5));//
console.log(f3(10));
}
this.f2 = function(x){
return x;
}
}
DEMO
Others have already told you what the problem is, so i will not repeat it. If you want your code to work, you just need a reference to this:
function AAA(){
var self = this;
this.f1 = function (){
console.log(self.f2(5)); //self.f2 exists, yay
}
this.f2 = function(x){
return x;
}
}
x = new AAA();
x.f1(); //5
So when I declare a variable outside the scope of any function, it becomes a property of the window object. But what about when I declare a variable inside the scope of a function? For example, in the following code I can treat x as a property of window, i.e., window.x, but what about y? Is it ever the property of an object?
var x = "asdf1";
function test() {
var y = "asdf2";
}
test();
It becomes a property of the Variable object associated with the function call. In practice, this is the same thing as the function call's Activation object.
I don't believe that the Variable object is accessible to running JavaScript code, though; it's more of an implementation detail than something you can take advantage of.
Access all local variables is a related question here on SO.
In order to declare a JS variable a property of an object you need to either use the new Object(); method or the {} syntax.
var variableName = new Object();
var variableName = {myFirstProperty:1,myNextProperty:'hi',etc};
Then you can assign child objects or properties to said variable object
variableName.aPropertyNameIMadeUp = 'hello';
variableName.aChildObjectNameIMadeUp = new Object();
As such the new variable object is associated with a method if it is within the method call.
Cheers
See following example (I have copy from other question-answer) very nice:
// a globally-scoped variable
var a=1;
// global scope
function one(){
alert(a);
}
// local scope
function two(a){
alert(a);
}
// local scope again
function three(){
var a = 3;
alert(a);
}
// Intermediate: no such thing as block scope in javascript
function four(){
if(true){
var a=4;
}
alert(a); // alerts '4', not the global value of '1'
}
// Intermediate: object properties
function Five(){
this.a = 5;
}
// Advanced: closure
var six = function(){
var foo = 6;
return function(){
// javascript "closure" means I have access to foo in here,
// because it is defined in the function in which I was defined.
alert(foo);
}
}()
// Advanced: prototype-based scope resolution
function Seven(){
this.a = 7;
}
// [object].prototype.property loses to [object].property in the scope chain
Seven.prototype.a = -1; // won't get reached, because 'a' is set in the constructor above.
Seven.prototype.b = 8; // Will get reached, even though 'b' is NOT set in the constructor.
// These will print 1-8
one();
two(2);
three();
four();
alert(new Five().a);
six();
alert(new Seven().a);
alert(new Seven().b);