If I create a callback within a function, can I get that callback to access the local variables within that function?
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = this.innerFunc;
callback();
}
Obj.prototype.innerFunc = function()
{
x++;
}
x naturally is not within the scope of innerFunc and will produce an error if called by itself. But if I call it from outerFunc can I extend innerFunc's scope in order to access x?
Edit: Should've mentioned that I don't want to pass arguments into the function or make x and instance of Obj. I'm more looking to treat innerFunc as though it was declared locally in outerFunc. Similar to what can be done below:
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = function() {
x++;
}
callback(); // works
}
Yes: this is exactly what function parameters are for. They allow you to pass a value from one scope into another.
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = this.innerFunc;
x = callback(x);
}
Obj.prototype.innerFunc = function(x)
{
x++;
return x;
}
Note that the value is sent to the other function, not the variable. So you need to return the value and assign it in order to use it.
If you're using prototypes, just set an instance property:
// constructor
var Obj = function () {}
Obj.prototype.outerFunc = function()
{
this.x = 0;
var callback = this.innerFunc.bind(this);
callback();
}
Obj.prototype.innerFunc = function()
{
this.x++;
}
var instance = new Obj()
instance.outerFunc()
console.log(instance.x) // returns 1
Edit: But #lonesomeday's answer is a much better solution as it takes a more functional approach avoiding side effects :)
The preffered way of doing this is to assign x to the scope of the object then all functions can access it, via this.x
Obj.prototype.outerFunc = function()
{
this.x= 0; // set x to zero
this.innerFunc();
}
Obj.prototype.innerFunc = function(x)
{
this.x++;
return this.x;
}
This is a bit hard to solve without knowing why you don't want to pass a parameter; if you just want to have a specific function signature, maybe a higher-order function might help?
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = this.innerFunc(x);
callback();
}
Obj.prototype.innerFunc = function(x)
{
return function () { /* use x in here */ };
}
This way you have two functions one inside the other. The outer one takes the parameter, and the inner one can access the variable that is passed to the outer one.
This of course only gives you half of what you demonstrate in your example: You can access the local variable but not modify it.
You can never access any function's internal variables from outside the function under any circumstances, in an OOP context or otherwise.
The only sort-of-exception is that a function A defined inside a function B, and returned from that function B, continues to have access to the variables in function B--the basic notion of closure.
I have no idea why you don't want to use instance variables. That's what they're for--sharing data across methods. I have no idea why you don't want to pass values in or out--that's what parameters and return values are for.
can I extend innerFunc's scope in order to access x?
No, you can't, whatever that means. There is no such notion in JS.
The closest you can come to what you seem to maybe want to do is to define the variable in the constructor:
function Obj() {
var x = 0;
this.outerFunc = function() {
var callback = this.innerFunc;
callback();
};
this.innerFunc = function() {
x++;
}
}
However, this will not work as-is because this.innerFunc is missing its context. Therefore, you would need to write
var callback = () => this.innerFunc();
However, it's a mystery why you would want to do this instead of just writing this.innerFunc().
Related
function emergency() {
var ambulance = 100;
var callAmbulance = function() { alert(ambulance); }
ambulance++;
return callAmbulance;
}
var accident = emergency();
accident(); // alerts 101
I am referring to the variable 'ambulance'.
When I call accident(); it should call emergency() which should use the declared variable 'ambulance' [considering the global scope thing in javascript, still it could set the value to global] but its using old value 101 instead of setting again back to 100 - behaving more like static var.
What's the Explanation?
What you have there is called a closure. It means a function can access variables declared in outer functions (or in the global scope). It retains access even after the 'parent' function has returned. What you need to understand is that you don't get a copy. The changes performed on that variable are visible to your inner function, which in theory means you could have multiple functions sharing access to the same variable.
function f () {
var x = 0;
function a() { x += 1; }
function b() { x += 2; }
function show() { console.log(x); }
return {a:a, b:b, show:show};
}
var funcs = f();
funcs.a();
funcs.b();
funcs.show(); // 3
One thing to be aware of is that a subsequent call to f will create a new scope. This means a new x variable will be created (new a, b, show functions will be created as well).
var newFuncs = f();
newFuncs.a();
newFuncs.show(); // 1
funcs.a();
funcs.show(); // 4
So, how do you get a copy? Create a new scope.
function g () {
var x = 0;
var a;
(function (myLocal) {
a = function () { myLocal += 1; }
}(x));
x += 200;
return a;
}
JS only has pass-by-value so when you call the anonymous function, the xvariable's value will be copied into the myLocal parameter. Since a will always use the myLocal variable, not x, you can be certain that changes performed on the x variable will not affect your a function.
If, by any chance, you're coming from a PHP background you are probably used to do something like
use (&$message)
to allow modifications to be reflected in your function. In JS, this is happening by default.
You are creating a function definition which is not compiled at this time:
var callAmbulance = function() { alert(ambulance); }
And before you are sending it to the called function, you are incrementing the num:
ambulance++;
And then you are sending it to the called function:
return callAmbulance;
But whether you are sending it there or not, it doesn't matter. The below statement executes or compiles the function:
var accident = emergency();
And this takes in the current ambulance value which is 101 after the increment. This is an expected behaviour in creating function but not executing it. Please let me know, if you didn't understand this behaviour. I will explain it more clearly.
I just learned OOP and there is one little thing that I am not able to solve. The problem is a scope issue of some sort.
If I create a new object then how will I be able to give it access to my constructor function if the constructor function is inside another function? Right now I get undefined. Storing the function in a global variable wont do the job.
var example = new something x(parameter);
example.i();
var getFunction;
var onResize = function() {
getFunction = function something(parameter) {
this.i= (function parameter() {
// Does something
});
};
};
window.addEventListener('resize', onResize);
onResize();
For OOP javascript, the pattern should be like this.
//defining your 'class', class in quotes since everything is just functions, objects, primitives, and the special null values in JS
var Foo = function (options) {
// code in here will be ran when you call 'new', think of this as the constructor.
//private function
var doSomething = function () {
}
//public function
this.doSomethingElse = function () {
}
};
//actual instantiation of your object, the 'new' keyword runs the function and essentially returns 'this' within the function at the end
var foo = new Foo(
{
//options here
}
)
If I understand you, you want to know how to access variables inside another function. Your attempt is reasonable, but note that getFunction is not bound until after onResize is called. Here's a bit of a cleaner demo:
var x;
function y() {
// The value is not bound until y is called.
x = function(z) {
console.log(z);
}
}
y();
x('hello');
A common JavaScript pattern is to return an object that represents the API of a function. For example:
function Y() {
var x = function(z) {
console.log(z);
}
return {
x: x
};
}
var y = Y();
y.x('hello');
You should definitely read up on the basic concepts of JavaScript. Your code and terminology are both sloppy. I'd recommend Secrets of the JavaScript Ninja. It does a good job explaining scope and functions, two tricky topics in JavaScript.
I want to pass a function reference "go" into another function "redefineFunction", and redefine "go" inside of "redefineFunction". According to Johnathan Snook, functions are passed by reference, so I don't understand why go() does not get redefined when I pass it into redefineFunction(). Is there something that I am missing?
// redefineFunction() will take a function reference and
// reassign it to a new function
function redefineFunction(fn) {
fn = function(x) { return x * 3; };
}
// initial version of go()
function go(x) {
return x;
}
go(5); // returns 5
// redefine go()
go = function(x) {
return x * 2;
}
go(5); // returns 10
// redefine go() using redefineFunction()
redefineFunction(go);
go(5); // still returns 10, I want it to return 15
Or see my fiddle http://jsfiddle.net/q9Kft/
Pedants will tell you that JavaScript is pure pass-by-value, but I think that only clouds the issue since the value passed (when passing objects) is a reference to that object. Thus, when you modify an object's properties, you're modifying the original object, but if you replace the variable altogether, you're essentially giving up your reference to the original object.
If you're trying to redefine a function in the global scope: (which is a bad thing; you generally shouldn't have global functions)
function redefineFunction(fn) {
window[fn] = function() { ... };
}
redefineFunction('go');
Otherwise, you'll have to return the new function and assign on the calling side.
function makeNewFunction() {
return function() { ... };
}
go = makeNewFunction();
Nothing is "passed by reference" in JS. There are times that references are passed, but they're passed by value. The difference is subtle, but important -- for one thing, it means that while you can manipulate a referenced object pretty much at will, you can't reliably replace the object (read: alter the reference itself) in any way the caller will see (because the reference was passed by value, and is thus merely a copy of the original reference; attempting to reassign it breaks in the same way it would if the arg were a number or string).
Some cowboys will assume you're redefining a global function and mess with it by name to get around the limitations of pass-by-value, but that will cause issues the second you decide not to have globals all over the place.
The real solution: return the new function, and let the caller decide what to do with it. (I'd argue that redefining functions right out from under the code that uses them is a pretty bad design decision anyway, but eh. I guess there could be a reason for it...)
Snook is wrong. And I don't think it's pedantic at all (#josh3736 :) to point out that EVERYTHING in JavaScript is pass by value. The article by Snook gets this COMPLETELY wrong. Passing a primitive and passing an object work the exact same way. These are equivalent:
var x = 2;
var y = x;
y = 3; //x is STILL 2.
function stuff(y){
y = 3; //guess what. x is STILL 2
}
stuff(x);
///////////////////
var x = {stuff: 2};
var y = x;
y = {stuff: 3}; //x.stuff is STILL 2
function stuff(y){
y = {stuff: 3}; //guess what. x.stuff is STILL 2
}
stuff(x);
This is important. Java, C#, and MOST languages work this way. That's why C# has a "ref" keyword for when you really do want to pass something by reference.
You can't modify the variable from inside the function, so the quick fix is to return the value and assign it outside the function, like this
// log() just writes a message to the text area
function log(message) {
$('#output').val($('#output').val() + message + "\n");
}
// redefineFunction() will take a function reference and
// reassign it to a new function
function redefineFunction() {
newvalue = function(x) { return x * 3; };
return newvalue;
}
// initial version of go()
function go(x) {
return x;
}
log(go(5)); // returns 5
// redefine go()
go = function(x) {
return x * 2;
}
log(go(5)); // returns 10
// redefine go() using redefineFunction()
go = redefineFunction();
log(go(5)); // returns 10, I want it to return 15
I believe functions are 'passed in by value'. If you put log(f(5)); inside your redefineFunction function it will output 15, but 10 when you call log(go(5)) afterwards.
If you change redefineFunction to return the function and then assign it to go (go = redefineFunction()) it will work as you expect.
This is equivalent to asking if you can redefine any variable by passing it as an argument to some function. No. You can reassign it by, uhh, reassigning it. In this case, if you make redefineFunction return a function, you can simply assign it to go:
function redefineFunction() {
var fn = function(x) { return x * e; };
return fn;
}
function go(x) {
return x;
}
go = redefineFunction();
go(5); // return 15
This is working in firefox:
function redefineFunction(fn) {
window[fn] = function(x) {
return x * 3;
}
};
function go(x) {
return x;
};
alert(go(5));
go=function(x) {
return x * 2;
}
alert(go(5));
redefineFunction('go');
alert(go(5));
The secret is that a global function called go also is called window.go and window["go"].
This can also be used at styles: element.style["overflow"] = "hidden", and in attributes:
element["value"] = "hello there".
This is a very useful knowlege.
Why dont use a object? something like this:
var o = {
go: function( x ) {
return x;
},
redefineFunction: function ( fn ) {
if (typeof fn === 'function') {
this.go = fn;
}
}
}
console.log(o.go(5)); // return 5
var fn = function (x) {
return x * 2;
};
o.redefineFunction(fn);
console.log(o.go(5)); //return 10
Hope it helps!
This is the javascript closure code I saw at Javascript Definitive Guide. I'd like to write it as C++11
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
This is the cpp code I wrote. But it isn't be compiled. Can C++11 represent the same expression?
auto c = []() -> int (*)() { int x = 0; return [&x]() -> int { return x++; }};
I'm using VS2010
Edit:
This is the full javascript sample code I made. You can test easily how the code works at your web browser.
<head>
<script language="javascript">
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
var uniqueID2 = (function()
{
var id = 0;
return function() { return id++; };
})();
</script>
</head>
<body>
<input value = "uniqueid1" type="button" OnClick="alert(uniqueID1());"></input>
<input value = "uniqueid2" type="button" OnClick="alert(uniqueID2());"></input>
</body>
</html>
OK, first let's break down what your JavaScript does.
function()
{
var id = 0;
return function() { return id++; };
}
This creates a function. A function with no name, which takes no parameters. This function, when called, will return a new function. The inner function will have access to a locally scoped variable, and this variable will be part of the state of that inner function.
Each time this function is called, it will return a new function. That new function will have its own state (var id = 0; has to do something, after all). Each call of the outer function will return a new function with new state.
This:
(function()
{
var id = 0;
return function() { return id++; };
})
Wraps the function in a pair of parenthesis. This is needed for operator precedence rules, to allow this to work:
(function()
{
var id = 0;
return function() { return id++; };
})()
This creates a function, and then calls the function. That's what the last () do at the end. It calls the outer function, which creates an inner function with its own scope and returns it.
In this expression, the outer function is lost. It's gone; you can't access it anymore. You created it for just long enough to call it, then let it drop into the trashcan of garbage collection.
Given all of this, we can see that this statement:
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
Creates the outer function, calls the function which returns a new function, and then stores the inner function in a variable called uniqueID1.
If you need proof that this is true, try this in your HTML:
var uniqueMaker = function()
{
var id = 0;
return function() { return id++; };
};
var uniqueID1 = uniqueMaker();
var uniqueID2 = uniqueMaker();
You'll get the same answer as your copy-and-paste version.
If we want C++ code to mimic this, we need to perform each step with proper C++ code.
First, the inner function. In C++, lexical scoping does not exist. So you cannot return functions that reference variables in other scopes. You can only return a lambda that has a copy of variables from another scope. Also, lambdas cannot modify scope unless you explicitly allow it. Thus, the inner code must look like this:
int id = 0;
return [=]() mutable { return ++id; };
That's all well and good, but now we need to create a lambda that will return this stateful lambda function. In C++, functions that have state are not the same as function pointers. And since the type of a lambda is compiler-defined, there's no way to type its name. Therefore, we must employ std::function as the return type of the outer function.
[]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
}
This creates a lambda function that, when called, will return an inner function with its own state. State that is independent from any subsequent calls to this function. Just like the JavaScript example.
Now, that's not enough. Remember, your JavaScript creates the outer function, calls it, and stores only its return value. The outer function itself is discarded. So we need to mimic this. Fortunately, this is easy enough in C++; it looks just like JavaScript:
([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})()
Lastly, we stick it in a variable:
auto uniqueID1 = ([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})();
The type of uniqueID1 will be std::function<int()>. It won't be the type of the outer function. The outer function is just a temporary that was used to create the inner scope.
I assume you're not asking for a literal translation, but rather how to best express this construct in C++. Your JavaScript construct is in some sense "faking a constructor", and your ID generator is best expressed as a simple class in C++. Then you just make instances of that class:
class UniqueID
{
unsigned int value;
public:
UniqueID() : value(0) { }
unsigned int operator()() { return ++value; }
};
Usage:
UniqueID gen1, gen2;
some_function(gen1());
another_function(gen2());
Foo x(Blue, "Jim", gen1());
This approach is lighter-weight than a std::function wrapper, although a straight-up lambda will produce a similar data structure (though you cannot know its type name). You can initialize value to -1 if you want the first ID to be 0 (though it might be useful to reserve 0 as a special value).
Are the JavaScript code snippets given below some sort of function declaration? If not can someone please give an overview of what they are?
some_func = function(value) {
// some code here
}
and
show:function(value){
// some code here
}
There are six ways/contexts in which to create functions:
1) Standard declarative notation (most familiar to people with C background)
function foo() {}
All the rest are function expressions:
2) As a method of an object literal
var obj = {
foo: function() {}
};
3) As a method of an instantiated object (created each time new is exectued)
var Obj = function() {
this.foo = function() {};
};
4) As a method of a prototype (created only once, regardless of how many times new is executed)
var Obj = function() {};
Obj.prototype.foo = function() {};
5) As an anonymous function with a reference (same effect as #1) *
var foo = function() {};
6) As an immediately executed anonymous function (completely anonymous)
(function() {})();
* When I look at this statement, I consider the result. As such, I don't really consider these as anonymous, because a reference is immediately created to the function and is therefore no longer anonymous. But it's all the same to most people.
The first one is simply creating an anonymous function and assigning it to a variable some_func. So using some_func() will call the function.
The second one should be part of an object notation
var obj = {
show:function(value){
// some code here
}
};
So, obj.show() will call the function
In both cases, you are creating an anonymous function. But in the first case, you are simply assigning it to a variable. Whereas in the second case you are assigning it as a member of an object (possibly among many others).
First is local (or global) variable with assigned anonymous function.
var some_name = function(val) {};
some_name(42);
Second is property of some object (or function with label in front of it) with assigned anonymous function.
var obj = {
show: function(val) {},
// ...
};
obj.show(42);
Functions are first-class citizens in JavaScript, so you could assign them to variables and call those functions from variable.
You can even declare function with other name than variable which that function will be assigned to. It is handy when you want to define recursive methods, for example instead of this:
var obj = {
show: function(val) {
if (val > 0) { this.show(val-1); }
print(val);
}
};
you could write:
var obj = {
show: function f(val) {
if (val > 0) { f(val-1); }
print(val);
}
};
One way of doing it:
var some_func = function(value) {
// some code here
}
Another way:
function some_funct() {
}
Yet another way:
var some_object={};
some_object["some_func"] = function() {};
or:
var some_object={};
some_object.some_func = function() {};
In other words, they are many ways to declare a function in JS.
Your second example is not correct.
The first one is a function declaration assigned to a variable (at least it should be, despite the fact that it's missing the variable type declaration first), the second one is probably related to a object declaration.
They are called anonymous functions; you can read more about them here:
http://www.ejball.com/EdAtWork/2005/03/28/JavaScriptAnonymousFunctions.aspx
The first example creates a global variable (if a local variable of that name doesn't already exist) called some_func, and assigns a function to it, so that some_func() may be invoked.
The second example is a function declaration inside an object. it assigns a function as the value of the show property of an object:
var myObj = {
propString: "abc",
propFunction: function() { alert('test'); }
};
myObj.propFunction();
The first one...
some_func = function(value) {
// some code here
}
is declaring a variable and assigned an anonymous function to it, which is equivalent to...
function some_func (value) {
// some code here
}
The second one should look like this...
obj = {
show:function(value){
// some code here
}
}
// obj.show(value)
and equivalent to...
//pseudo code
class MyClass {
function show (value) {
// some code here
}
}
obj = new MyClass(); // obj.show(value)
Cheers