Use function of another scope to access variable of current execution context - javascript

I am developing a widget inside a framework so that I would need to log variable "a" using a pattern like the one below. How do I "call" this function log_a so it can access the variable declared in the execution context it is called from? i.e. Have the console output "a value", instead of the current error of not able to find variable "a".
(function(global) {
global.log_a = function() {
console.log(a);
};
}(window));
var anotherFunction = function() {
var a = 'a value';
log_a();
};
anotherFunction();
edit:
I tried to make the example simple to make the question easier to follow but I now see it led to confusion. Update with more clarifications:
The first part of the code is trying to emulate my effort of moving large functions to a different file for cleaner code.
I am using a library where one input is a function and it will always pass one parameter to it, so I have no option of adding extra arguments (i.e. the answers suggesting to put "a" as an argument).
The trick of declaring "a" as global works and it is what I am currently using, but I thought this wasn't the best practice.
So my questions is (I am guessing the answer is "it is not possible") if there is some way to call log_a so it behaves like if the code was like this:
var anotherFunction = function() {
var a = 'a value';
var log_a = function() {
console.log(a);
};
};
anotherFunction();

You can use function arguments to pass the value of a to your log_a method. The issue that you are currently happening is that var a = 'a value' is unknown to the log_a as it is defined within another function. This is because a variable declared with var in a function scope cannot be accessed outside that function scope. Thus, you are better of doing something such as the following:
(function(global) {
global.log_a = function(a) { // retrieve 'a' as an argument in the log_a method
console.log(a); // print the argument passed through
};
}(window));
var anotherFunction = function() {
var a = 'a value';
log_a(a); // pass through 'a' into the `log_a` method
};
anotherFunction();

You can pass variable a value from that function so log_a() function can access that variable value.
(function(global) {
global.log_a = function(a){
console.log(a);
};
}(window));
var anotherFunction = function() {
var a = 'a value';
log_a(a);
};
anotherFunction();

Variable a exists only in the scope of function anotherFunction;
(function(global) {
global.log_a = function() {
console.log(a);
};
}(window));
var anotherFunction = function() {
// var a exists only here, inside this function
var a = 'a value';
// log_a is another function, it has its own scope,
// and it doesn't know about var a
log_a();
};
anotherFunction();
You can either pass the variable a as an argument to log_a, like log_a(a) inside anotherFunction, or make the variable a available to both anotherFunction and log_a functions:
var a = 'a value';
(function(global) {
global.log_a = function() {
console.log(a);
};
}(window));
var anotherFunction = function() {
log_a();
};
anotherFunction();

Related

Swapping variables within a method

I'm trying to learn some OOP, so bear with me. I need to use a variable I defined in one function, elsewhere. Here is my example code (I want INTERCEPT!! to be logged, but it returns undefined):
function Talk() {
var greeting;
var pleaseStop; // declare it
this.A = function () {
greeting = 'hello';
console.log(greeting);
var intercept = function () {
pleaseStop = 'INTERCEPT!';
}
}
this.B = function () {
greeting = 'goodbye';
console.log(pleaseStop); // this returns undefined!
console.log(greeting);
}
}
var activateTalk = new Talk();
activateTalk.A();
activateTalk.B();
This whole code logs the following:
hello
undefined
goodbye
I have also tried intercept.pleaseStop() but it still returns undefined. Would anyone know of a solution?
EDIT:
I've removed the var the second time, but it still returns undefined:
http://jsfiddle.net/d654H/2/
var pleaseStop = 'INTERCEPT!';
You're declaring a new, function-local variable here; drop the var to assign to the existing variable in scope.
Then, you need to actually call intercept; at the moment you only define it.
It's your choice as to when you call that function; in this live example I simply do so immediately after the definition, for the purposes of exposition.
Remove var in front of the assignment to pleaseStop.
This assigns a new value to the pleaseStop declared inside the constructor, which is visible also from inside B:
var intercept = function () {
pleaseStop = 'INTERCEPT!';
}
This declares a new local variable pleaseStop, completely unrelated to the other pleaseStop, that is not visible outside intercept:
var intercept = function () {
var pleaseStop = 'INTERCEPT!';
}
If you do the latter instead of the former, you end up changing the value of another variable than the one you intended.
Your problem is you never set pleaseStop. You have declared intercept as a function, but you never called it. Therefore, pleaseStop is undefined.
Firstly you have't called intercept() anywhere and also u did something
var pleaseStop = 'INTERCEPT!';
which will create new variable instead of initializing global variable
You can do something like this
function Talk() {
var greeting;
var pleaseStop; // declare it
this.A = function () {
greeting = 'hello';
console.log(greeting);
var intercept = function () {
pleaseStop = 'INTERCEPT!';//changed
}
intercept(); //..Added
}
this.B = function () {
greeting = 'goodbye';
console.log(pleaseStop); // this returns undefined!
console.log(greeting);
}
}
var activateTalk = new Talk();
activateTalk.A();
activateTalk.B();
Without var keyword.
var pleaseStop = "A";
function foo(){
pleaseStop = "B"; // overwriting to "B"
}
foo();
alert(pleaseStop); // shows "B"
With var keyword.
var pleaseStop = "A";
function foo(){
var pleaseStop = "B"
// This defines a new variable 'pleaseStop'
// in the scope of function foo(){}.
}
foo();
alert(pleaseStop); // shows "A"
Variable Scope
JavaScript has function-level scope. In most languages which have block-level variable scope, variable are accessible whithin their block surrounded by curly brackets ({and}). But JavaSciprt doesn't terminate scopes at the end of blocks, but terminate them at the end of functions.
I'm sure there are many articles and documents about it. I googled it and found an intresting introductory article.
http://javascriptissexy.com/javascript-variable-scope-and-hoisting-explained/
Hope this helps.

Is it possible to modify a function itself when its property function is called?

Basically I want to do this:
someFunction() // do something
someFunction.somePropertyFunction()
someFunction() // Now someFunction is modified; it should now exhibit a different behaviour
Is this possible?
EDIT:
I'm not looking for what #Kolink was suggesting. Basically I want to augment a function's functionality by calling one of it's property function.
Specifically, I need to: 1. have access to the original function inside my property function (which is entirely doable using this), and 2. bind a new function to the original function's name (which I'm not sure if it's possible).
Just to be clear, I don't have access to the internal definition of the function that I want to augment. I want to attach a function to Function.prototype (so that it will be available as a property of the function that I want to augment), and then I will call func.augmentThis(), and then func should be augmented. But I'm not sure how, hence the question :P
Easily. Here's an example:
var derp = 123;
someFunction = function() {alert(derp);};
someFunction.somePropertyFunction = function() {derp = 456;};
someFunction(); // alerts 123
someFunction.somePropertyFunction();
someFunction(); // alerts 456
Okay, that's an oversimplified example, but yeah, it's entirely possible.
If your question is whether a function attached as a property to another function has a way to access the function to which it is attached, the answer is no. After all, the same function could be attached to any number of functions of objects.
So one alternative is to explicitly refer to the "mother" function within the function that is attached to it and intended to change its behavior:
function f (n) { alert (n + f.offset); }
f.offset = 0;
f.change_offset = function (i) { f.offset = i; };
f (1); //1
f.change_offset (100);
f (1); //101
Here, f is hard-wired into the definition of change_offset. If this bothers you, or you want something slightly more general, write a little routine to set a function as a property on another function, while binding its this to the function being attached to:
function set_func_as_func_prop ( propname, func_to_set, func_to_set_on ) {
func_to_set_on[propname] = func_to_set.bind(func_to_set_on);
}
Now you can write the function more generally
function change_offset (i) {
this.offset = i;
}
and set it on f or any other function.
set_func_as_func_prop ("change_offset", change_offset, f);
set_func_as_func_prop ("change_offset", change_offset, g);
Sort of:
function someFunction() {
return realFunction.apply(this, arguments);
}
function someFunctionA(name) {
return 'Hello, ' + name + '!';
}
function someFunctionB(name) {
return 'Goodbye, ' + name + '...';
}
var realFunction = someFunctionA;
someFunction.somePropertyFunction = function () {
realFunction = someFunctionB;
};
Sure it's possible. It's not recommended, but it's possible. For example:
function a() {
alert("a");
}
function b() {
alert("b");
}
function c() {
return c.f.apply(this, arguments);
}
c.f = a;
c.toggle = function () {
c.f = c.f === a ? b : a;
};
Now let's test it:
c(); // alerts "a"
c.toggle();
c(); // alerts "b"
See the demo: http://jsfiddle.net/LwKM3/
I want to attach a function to Function.prototype. Then I need to bind a new function to the original function's name (which I'm not sure if it's possible).
That indeed is impossible, you don't know what refers to the function. And you cannot change the internal representation of a function, which is immutable.
The only thing you can do is to create a new function and return that, to let the caller of your method use it somehow - specifically assigning it to the original variable:
somefunction = somefunction.augmentSomehow();
Your method for that will look like this:
Function.prototype.augmentSomehow = function() {
var origFn = this;
return function() {
// in here, do something special
// which might include invoking origFn() in a different way
};
};
Not sure if this helps, but I would implement described problem in following way:
// defined by somebody else - unknown to developer
var someFunction = function() {
alert("this is initial behavior");
}
someFunction(); // returns "this is initial behavior"
// defines parent object on which someFunction() is called
var parentObject = this; // returns window object (as called direclty in the
// browser)
// if you are calling someFunction from some object (object.someFunction())
// it would be:
// var parentObject = object;
// augumentThis definition
someFunction.augumentThis = function() {
var newFunction = function() {
alert("this is changed behavior");
};
parentObject.someFunction.somePropertyFunction = function() {
parentObject.someFunction = newFunction;
parentObject.someFunction();
};
};
someFunction.augumentThis(); // change function behavior
someFunction(); // "this is initial behavior"
someFunction.somePropertyFunction(); // "this is changed behavior"
someFunction(); // "this is changed behavior"

Javascript inner function with colon

I know that you can write following
var obj = {
test: 'something'
}
But in this code, the inner function does not refer to a variable, but to a function.
Is there any other way to write / call the inner function?
function outer(){
var a = "Outerfunction";
console.log(a)
innerFct: function InnerFct() {
var c = "Inner";
console.log(c)
} innerFct();
}
window.outer();
There are a couple of different things going on here.
In this code:
var obj = {
test: 'something'
}
you are using "literal object notation" to create -- well, an object with one property test and that property has a value of something
In your second case, you are creating a code block (yes, it is fun that both objects and code blocks use the same syntax {...} to define them.
Inside of a code block, the innerFct: becomes a label. Labels are used with some control flow statements to jump around. Forget about them, you really are better off not using them.
function outer(){
var a = "Outerfunction";
console.log(a)
function innerFct() {
var c = "Inner";
console.log(c)
}
innerFct();
}
outer();
or even
function outer(){
var a = "Outerfunction";
console.log(a)
var innerFct = function () {
var c = "Inner";
console.log(c)
}
innerFct();
}
outer();
You are confusing functions with objects.
When using an object, the colon is used to show key-value pairs.
var object = {
innerFct: function(){
console.log('rawr');
},
someVariable: 7
}
object.innerFct(); //logs rawr
object.someVariable = 4; //just changed from 7 to 4
Using a colon how you have it in your example is incorrect syntax. Also when you are creating a function within an object like that, you don't name the function again because you are already assigning it to a name on the object.
Then you can edit the function anytime by doing something like this:
object.innerFct = function(){
//new code
}
Doing object.innerFct() will call the function.
Other answers have sufficiently covered the object syntax and calling the function in scope. As I mentioned in the comment, you can just do this:
function outer(){
(function () {
var c = "inner";
console.log(c)
})();
}
window.outer();
And it logs inner just fine.
Edit: Private/hidden variables like innerFct in the original code sample can be captured in closures as well.
outer = function() {
var innerFct = function () { console.log("inner"); }
// innerFct is captured in the closure of the following functions
// so it is defined within the scope of those functions, when they are called
// even though it isn't defined before or after they complete
window.wrapper = function() { innerFct(); }
return function() { innerFct(); }
}
outer();
// each of these next three lines logs "inner"
window.wrapper(); // assigned to global variable
outer()(); // calling the returned function
var innerFctBackFromTheDead = outer(); // saving the returned function
innerFctBackFromTheDead();
There is also the object constructor/prototype syntax.
function Outer() {
this.inner = function() {
this.c = "inner";
console.log(this.c);
}
}
var out = new Outer();
out.c; // undefined
out.inner(); // logs "inner"
out.c; // "inner"
More information on the new keyword and prototypes: http://pivotallabs.com/javascript-constructors-prototypes-and-the-new-keyword/

Is this proper javascript for making a namespace that encapsulates various methods into different objects?

var namespaced = {
A: function(){
function r(){
//do some stuff
return something;
}
var someProperty = 5;
function j(){
//do some more stuff
return something;
}
},
B: function(){
//can I call A and C?
A.r();
C.d();
},
C: function(){
function d() {
//do stuff we like
}
}
}
Then I could do...
namespaced.A.j();
namespaced.C.d();
something = namespaced.A.someProperty;
right?
Would I need to do this too?
var something = new namespaced.A()?
If so does A() have a constructor? I'm really confused here :{
I'm trying to encapsulate my javascript so it's easy to maintain
Then I could do...
namespaced.A.j();
namespaced.C.d();
something = namespaced.A.someProperty;
No you couldn't. The function j and someProperty are only local to A and are not propagated to the outside. If you want to access them from the outside, you have to make them a property of the function, using this:
var namespaced = {
A: function(){
this.r = function(){
//do some stuff
return something;
};
this.someProperty = 5;
this.j = function(){
//do some more stuff
return something;
};
}
}
But you would still need to call var a = new namespaced.A() in order to access the functions.
If you want to call namespaced.A.j() directly, you would have to declare A as object, not as function:
var namespaced = {
A: {
r: function(){
//do some stuff
return something;
},
someProperty: 5,
j: function(){
//do some more stuff
return something;
}
}
}
So it depends on what you want to achieve eventually... to get a better insight into these methods, I recommend JavaScript Patterns.
This is what you need to understand about JavaScript:
When you write
var obj = { A: a, B: b, C: c };
you are creating (and assigning to obj) an object with properties called A, B and C mapping to values a, b and c respectively. These values may very well be functions, so when you have
var obj = { A: function(){...} };
you are creating an object with a property called "A" which is a function. You can refer to it with obj.A and call with obj.A().
When you call obj.A(), the keyword this inside the body of function A will refer to obj. You can use it to assign new properties to obj:
var obj = {
A: function() { this.prop = "Hello!"; }
};
obj.A();
alert( obj.prop ); // alerts "Hello!"
So, inside namespaced.A.j() the this keyword will point to namespace.A (it's what is to the left of the last dot).
You can apply a function to an object like so: func.apply(obj) or like so: func.call(obj). In this case, the this keyword will refer to obj instead. This isn't relevant to your case, but if func takes parameters (let's say param1 and param2), you can apply the function like so: func.apply(obj, [val1, val2]) or like so: func.call(obj, val1, val2).
All variables declared inside a function live only inside that function. They are not visible outside. And when you write function doStuff(){} it's (I'm simplifying here) as good as if you wrote var doStuff = function(){}; So nested functions live and can be used only inside the surrounding function; that is, unless you assign them to something accessible from outside.
When you call something like new Cons() what happens is the creation of a new empty object followed by the application of Cons() on that object. In other words, it's the same as
var obj = {};
Cons.apply(obj);
or if you prefer:
var obj = {};
obj.Cons = Cons;
obj.Cons();
// obj's Cons property then mysteriously disappears
// unless it was explicitly set inside Cons() (oh my, how confusing! :)
So you can have this:
function Duck(name){
this.myName = name;
this.quack = function(){
alert(this.myName + " quacks!");
}
};
donald = new Duck('Donald');
donald.quack();
With all the preceding in mind, a way to write namespaced code is like this:
// The following syntax, confusing to someone who hasn't seen it before,
// is defining a new anonymous function and immediately using it
// as a constructor applied to a new empty object.
//
// Alternatively, you can use this syntax:
// var namespaced = {};
// (function(){
// ....
// }).apply(namespaced);
//
var namespaced = new (function(){
// This creates a new variable named "namespaced"
// which is visible only inside this anonymous function.
// This variable points to the still-empty object created by
// 'new'. This object will, once we're done with this anonymous function,
// be assigned to a variable, outside, which by "coincidence" is
// also named "namespaced".
var namespaced = this;
// You could alternatively not create the variable "namespaced"
// and use 'this' directly inside this anonymous function. But,
// the 'this' keyword may point to different objects inside the
// nested functions that follow, so we create it to avoid confusion.
// This assigns a new object to variable 'A', which isn't visible outside.
// Use a constructor function defined inline.
var A = new (function(){
var A = this; // 'this' now refers to the empty object created just above
this.someProperty = 5; // Two different ways of
A.anotherProperty = 7; // doing mostly the same thing
this.j = function(){
//do some more stuff
// 'this' will point to j, here
return something;
}
// Function r isn't visible outside of A's constructor like this!
function r(){
//do some stuff
return something;
}
// Make 'r' visible outside by assigning it to a property of 'A'.
// Look, it's also called "r". What fun!
A.r = r;
})();
// Make the object in variable 'A' visible outside of
// 'namespaced's constructor, by making it a property of 'namespaced'
namespaced.A = A;
// Create a new object as before.
// This time we won't make it visible outside
// of "namespaced"'s constructor.
var C = new (function(){
this.d = function (){
//do stuff we like
}
})();
// Give "namespaced" a property 'B'.
// This time it's a function instead of a nested object.
namespaced.B = function(){
// It's cool to make these function calls here, because
// (a) nested functions can see the variables ('A' & 'C')
// of surrounding functions, even if they terminate in the meantime;
// and (b) 'r' & 'd' are properties of 'A' and 'C'.
A.r();
C.d();
};
// You could return 'this' or 'namespaced' from this constructor,
// but the 'new' keyword will make sure the "namespaced" variable
// outside will get the no-longer-empty object it created,
// so you can just not return anything.
})();
// Now you can do
five = namespaced.A.someProperty;
seven = namespaced.A.anotherProperty;
something = namespaced.A.j();
namespaced.B(); // Calls A.r() and C.d()
// But you can't do
namespaced.C.d(); // WRONG: "namespaced" doesn't have a property named "C"
I hope this helps more than it confuses.

javascript - shortcut for calling a function at the same time it is defined

to call a function at the same time it's defined, i had been using:
var newfunc = function() {
alert('hi');
};
newfunc();
is the following the correct way of combining these 2:
var newfunc = function() {
alert('hi');
}();
There could be a number of reasons you wish to do this. I'm not sure what yours are, but let me introduce a couple of favourite patterns:
Pattern #1: A singleton. The function is executed and then becomes a singleton object for use by other components of your code.
var singletonObject = new function() {
// example private variables and functions
var variable1 = {};
var variable2 = {};
var privateFunction = function() {
};
// example public functions
this.getData = function() {
return privateFunction(variable1, variable2);
};
// example initialisation code that will only run once
variable1.isInitialised = true;
};
Pattern #2: Self-executing anonymous function ... handy for sooo many reasons!
// Declare an anonymous function body.
// Wrap it in parenthesis to make it an "expression.
// Execute it by adding "();"
(function(){})();
And here's an example that also creates a namespace for your objects.
I'm using "NS" as an example namespace:
// declare the anonymous function, this time passing in some parameters
(function($, NS) {
// do whatever you like here
// execute the function, passing in the required parameters.
// note that the "NS" namespace is created if it doesn't already exist
})(jQuery, (window.NS = window.NS || {}));
You can also set the context of a self-executing function by using .call or .apply instead of the usual parenthesis, like this:
(function($){
// 'this' now refers to the window.NS object
}).call(window.NS = window.NS || {}, jQuery);
or
(function($){
// 'this' now refers to the window.NS object
}).apply(window.NS = window.NS || {}, [jQuery]);
var newfunc = function f() {
alert("hi!");
return f;
}();
Having a named function expressions allows the function to recursively call itself or, in this case, return itself. This function will always return itself, however, which might be an annoyance.
No. Your second example will immediately call the anonymous function and assign its return value to newfunc.
adamse describes an approach which appears to work. I'd still avoid the approach as the two step process is easier to read and thus will be easier to maintain.
If I understand your question correctly, give this a try:
(f = function (msg) {
msg = msg ? msg : 'default value';
alert(msg); }
)();
f('I\'m not the default value!');
You'll get two alerts, the first one will say "default value" and the second will say "I'm not the default value. You can see it in action at jsBin. Click 'preview' to make it run.
you could do like this:
o = {};
o.newfunc = ( function() {
function f() {
alert('hi');
}
f();
return {
f : f
};
}
)();
then calling the function like:
o.newfunc.f();
will also render an alert message

Categories

Resources