I'm learning JS and am wondering, is there a way to return the function bar() or buz() by without returning foo()? For example, if I wanted to return the function bar(); to get 2, could I do that? Would it be something like foo().bar(); ?
// Nested Scopes
function foo() { // can only access itself
var a = 1;
function bar() { // access to foo(), not buz()
var b = 2;
function buz() { // access to bar() and foo()
var c = 3;
console.log(a, b, c); // 1, 2, 3
}
buz();
console.log(a, b); // 1, 2
}
bar();
console.log(a); // 1
}
foo(); // 1
Certainly. You can return an object at each stage which holds the function, or you can return the function itself. This utilizes what's called a closure.
function foo() {
var a = 1;
function bar() {
var b = 2;
function buz() {
var c = 3;
console.log(a, b, c);
}
console.log(a, b);
return { buz: buz };
}
console.log(a);
return { bar: bar };
}
foo().bar().buz();
You can do this, but it’s quite over-complicated.
The basic syntax is:
foo().bar().buz();
Where-ever you add another () after an existing one, it’ll print that level out. See the snippet for examples.
// Nested Scopes
function foo() { // can only access itself
var a = 1;
function bar() { // access to foo(), not buz()
var b = 2;
function buz() { // access to bar() and foo()
var c = 3;
return (function() {
console.log(a, b, c);
});
}
return (function() {
var tmp = function() {
console.log(a, b);
return {
buz: buz
};
};
tmp.buz = buz;
return tmp;
})();
}
return (function() {
var tmp = function() {
console.log(a);
return {
bar: bar
};
};
tmp.bar = bar;
return tmp;
})();
}
foo().bar().buz(); // (nothing)
foo().bar()().buz(); // 1, 2
foo()().bar()().buz(); // 1 // 1, 2
foo()().bar().buz()(); // 1 // 1, 2, 3
foo()().bar()().buz()(); // 1 // 1, 2 // 1, 2, 3
This kind of abuses the fact that you can assign properties to anything in JavaScript, including functions.
foo is a function that refers to the outer foo.
foo() is another function that refers to that inner tmp which has a bar property that refers to the inner bar function.
foo()() actually calls that inner tmp function but still leaves you with an object that has a bar property that again refers to the inner bar function.
This approach is basically the same for bar.
For buz, however, (something).buz() is just a function, without any extra properties and (something).buz()() doesn’t return anything, because that’s the final level.
you do this more like setting a variable.
var foo = {
bar: function() {
return 3;
}
}
console.log(foo.bar());
Related
var obj = {
a: 2,
}
var a = 3;
const func = () => {
console.log(this.a);
}
function test() {
setTimeout(func, 100);
}
function test2() {
setTimeout(() => {
console.log(this.a);
}, 100);
}
test.call(obj); //3
test2.call(obj); //2
It seemed that the test and test2 are the same, but the returned result is different, what's the problem with 'this'?
with test arrow function, this will refer to the window object, and as var a = 3, the a will be assigned as a property to the window, it will be like
window.a
But in test2 this will refer to the obj object.
See the following code:
function parent(child) {
var a = 4;
var b = 5;
child();
}
parent(function() {
console.log(a + b);
})
Here I understandably get:
Uncaught ReferenceError: a is not defined.
Is there anything I can do to change only the parent function so that the console.log() in the child function has access to a and b so that it can reference it in that way?
I know I can pass a and b into child as arguments, but I'm wondering if I can somehow call the child function with the parent scope injected into it so that I don't need to list the parameters in the child function.
I also looked at .call(), .apply(), and .bind(), but it seemed that would only help if I wrote this.a and this.b in both parent AND the child function.
You could use the window (by referencing this) to add globals to it, but this method isn't very nice, to say the least:
function parent(child) {
var a = 4;
var b = 5;
this.a = a;
this.b = b;
child();
}
parent(function() {
console.log(a + b);
})
Another ugly solution would be to use eval, which I do not reccomend either:
function parent(child) {
var a = 4;
var b = 5;
eval('var f = '+child);
f();
}
parent(function() {
console.log(a + b);
})
You're most likely better of passing through the variables like you mentioned above:
function parent(child) {
var a = 4;
var b = 5;
child(a, b);
}
parent(function(a, b) {
console.log(a + b);
})
Or, you could wrap your child function in a wrapper function (i.e. make it a closure), which can accept parameters a, b, for your child() to use like so:
function parent(child_wrapper) {
var a = 4;
var b = 5;
var child = child_wrapper(a, b);
child();
}
parent(function(a, b) { // wrapper function
return function() { // original child function (untouched, just being returned by the wrapper function)
console.log(a + b);
}
})
It is possible to global a variable inside a function, if not, how can I access a var in function b from function a.
var money;
var moneyInput = document.getElementById('input');
function check(){
if (moneyInput.value == "") {
money = 100;
}
function hit() {
document.write(money) // will this money var be 100 or undefined?
}
Just declare that variable outside function and then use it inside of that function.
P.S Please, post some code that you tried already.
let a = 5;
let b = 0; // Declare global variable
function printAB(_b) {
b = _b; // Set new value through this function
console.log(a, b);
}
function printBC() {
let c = 7;
console.log(b, c); // Get b variable
}
printBC(); // 0, 7 // b = 0
printAB(2); // 5, 2
printBC(); // 2, 7 // b = 2
Edit
With code you provided, answer is simple. Variable money can be equal 100 or be undefined, that depends if function hit will be called before function check.
If you assign a value to an undeclared variable in a function it will be created as a global variable.
You should declare the variable outside of the function scope:
var myGlobalVar = "foo";
function a(){
var myLocalVar = 'bar';
alert(myGlobalVar); //shows foo
alert(myLocalVar); //shows bar
}
function b(){
var myLocalVar = 'baz';
alert(myGlobalVar); //shows foo too
alert(myLocalVar); //shows baz
}
Assign a variable without using var, let, or const
var foo = 'bar';
function fn() {
console.log(foo);
bar = 'xyz';
}
fn()
console.log(bar)
Repl: https://repl.it/languages/javascript
You can assign a value to the global object ( window in browsers):
function a(){
window.test="test";
}
function b(){
console.log(test);
}
a(),b();
Declaring the variable on the outer scope and using it inside should solve your problem. However if you insist on creating a variable on the global scope you can do the following;
window.VAR_NAME = 'foo';
By doing so you are actually creating a global variable VAR_NAME and it now has the value foo.
/* 1 */
var a = 'sample text';
function one() {
a = 'modified text';
}
function two() {
console.log(a);
}
one();
two();
/* 2 */
function one(callback) {
var a = 'sample text callback';
callback(a);
}
function two() {
one(function(a) {
console.log(a);
});
}
two();
/* 3 */
var one = new Promise(function(resolve, reject) {
var a = 'sample text promise';
resolve(a);
});
function two() {
one.then(function(a) {
console.log(a);
});
}
two();
/* 4 */
var myGlobals = {};
function one() {
myGlobals.a = 'sample text';
}
function two() {
console.log(myGlobals.a);
}
one();
two();
I found this code in a book:
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // 2
What does last line mean?
The last line is doing an assignment and then calling the function.
Assignment happens first
(p.foo = o.foo)
Then call the function
(p.foo = o.foo)();
In this second call to foo, it is being called outside of the scope of p or o, so it's essentially the same as calling:
foo();
I have the following scenario. I have an object 'a' with two callback methods however one callback requires access to the other callback variable value (for modifications / to read value / update value). I would like to know what is the best approach to structuring this code without placing the variable b into global scope. Under is the code and a jsfiddle.
Code
var a = {
load: function(){
var b = 25;
console.log(b);
},
add : function (b){
console.log('The value of b is '+ b);
}
};
Use a closure:
var module = (function () {
var b; //Scoped to this module
return { //Return object with methods
load: function () {
b = 25; //This refers to the module's b
console.log(b);
},
add: function () {
console.log('The value of b is '+ b);
}
};
})(); //Self invoking function, invokes instantly.
module.load(); //b is now 25.
module.add(); //The value of b is 25
console.log(b); //undefined, out of scope.
Now all the "private" variables are scoped directly to the module, and don't affect global scope.
// Alternative 1: Using a "private" variable
function A(b) {
// seal b in closure
var b = b;
this.load = function(){
b = 25;
console.log(b);
};
this.add = function(){
console.log('The value of b is '+ b);
};
this.getB = function(){
return b;
};
}
// Alternative 2: Using a object property
function A(b) {
// seal b in closure
this.b = b;
this.load = function(){
this.b = 25;
console.log(this.b);
};
this.add = .add = function(){
console.log('The value of b is '+ this.b);
};
}
var a = new A('foo');
var callback = a.load;
// ...