Can a function read the binding of another function? - javascript

I'm currently learning javascript and I would appreciate some help.
I've been playing around trying to create a program that would multiply two numbers without using the * operator. I already found an easier way to do it than my approach but I'd like to know why the code I wrote doesn't work:
function addToItself(a) {
a = a + a;
return a;
}
function times(b) {
for (count = 0; count < b; count++) {
addToItself(a)
}
return a;
}
function multiply (x, y) {
a = x;
times(y);
}
let output = multiply(5, 2);
alert(output);
Is it not working because the binding "a" in the addToItself function has a local scope and the multiply function can't read it or is it something else?
Thanks a lot in advance!

The issue is with the scope of each variable. In JavaScript, a variable declated within a function is scoped to that function. This means that a variable declared within a function can only be accessed within the function. Scopes are nested, so a variable declared globally is accessible inside a function too, though that's often discouraged.
Additionally, function arguments (such as a in addToItself and b in times) are treated like variables scoped to the function.
I would advise looking at the MDN docs for "scope" and familiarizing yourself with how variables are scoped in JavaScript.
I have included a fixed version of your code is below, for reference:
function addToItself(a) {
// I used a new variable here since reassigning to an argument is discouraged
const twoA = a + a;
return twoA;
}
console.log('5 + 5 = ' + addToItself(5));
function times(value, times) {
let temp = 0;
for (let count = 0; count < times; count++) {
temp += value;
}
return temp;
};
console.log('5 * 5 = ' + times(5, 5));

No you can't read variable inside another function, there are easier way, like
function multiply(x, y) {
var result = 0;
for (var count = 0; count < y; count++) {
result += x
}
return result;
}
console.log("5 * 2 = " + multiply(5, 2));

Related

No return statement in sub-functions? [Javascript]

I'm in Chapter 3 - Functions of Eloquent Javascript.
Everything about the following code makes sense to me -- except one thing.
Why don't the sub-functions (for lack of a better term) have return statements?
var landscape = function() {
var result = "";
var flat = function(size) {
for (var count = 0; count < size; count++)
result += "_";
};
var mountain = function(size) {
result += "/";
for (var count = 0; count < size; count++)
result += "'";
result += "\\";
};
flat(3);
mountain(4);
flat(6);
mountain(1);
flat(1);
return result;
};
console.log(landscape());
// → ___/''''\______/'\_
Maybe I'm missing something fundamental about the purpose of the return statement, even after reading different definitions from different sources.
I've tried adding return statements to the sub-functions. I've found that it'll either terminate the sub-function pre-maturely, or produce the same result as if it was never there.
Thanks for reading.
They are accessing the outer scoped variable result and change something there. So they change the actual result variable's value and doesn't need to return anything. If it reaches to the end of the function, function ends. You can do the same by creating local function scoped variables and make strings from them, return them and concatenate in the main landscape function.
See the alternative of your code with the return statements
var landscape = function() {
var result = "";
var flat = function(size) {
var localFlat = ''; // Function scoped variable
for (var count = 0; count < size; count++) {
localFlat += "_";
}
return localFlat; // Return function scoped variable
};
var mountain = function(size) {
var localMountain = "/"; // Function scoped variable
for (var count = 0; count < size; count++) {
localMountain += "'";
}
localMountain += "\\";
return localMountain; // Return function scoped variable
};
result = flat(3) + mountain(4) + flat(6) + mountain(1) + flat(1); // Concatenate the results of each function
return result;
};
console.log(landscape());
Because your sub-functions affect your global landscape variable - result and in the end, function return result variable..This example shows you that you can change global variables into sub-functions..

How to change a global variable with an if/else statement

I have this code where i want to change var n if the var thisRoll is not 'green', but i only get undefined in the output from console.log(n)
var thisRoll = 'red'
var n;
var base_bet = 1;
function betInput(thisRoll, n) {
var x;
if (thisRoll === 'green') {
x = base_bet;
n = 0;
} else {
n = n + 1;
}
return x;
}
var X = betInput(thisRoll);
console.log(X);
console.log(n);
Shouldn't it add 1 when the thisRoll aren't 'green'?
Because your n is also a parameter in the function. So it hides the outer variable n in the function and when you access the n, it refers to the parameter variable. To work with the global n, you need to remove the parameter, or change it's name.
function betInput(thisRoll) {
var x;
if (thisRoll === 'green') {
x = base_bet;
n = 0;
} else {
n = n + 1;
}
return x;
}
The function betInput(thisRoll, n) contains a parameter n which shadows the global variable n. Calling that function using betInput(thisRoll) merely sets the local n to a default value.
(The fact that Javascript is lax on this - and many other things - does make it difficult to write stable code in the language).
Simply remove n from the function parameter list and all will be well.
Remove the parameter in your function. There's n there, which makes it scoped to the function.
function betInput(thisRoll, n) {
//------------------------^^^
Change your function to:
function betInput(thisRoll) {
So that, n will reference your global variable, otherwise n is undefined in your function scope

Passing Javascript Parameters and Assigning to Variables

i want to pass one function generated value to another function.
example :
function mainFunc(){
var x = 1;
}
function doMatch(){
var tot = x + 1;
}
only if doMath() Function calls it will calculate total. it shouldn't call mainFunc() Again.
not like this
function mainFunc(){
var x = 1;
return x;
}
function doMatch(){
var tot = mainFunc() + 1;
}
How can i do this. i think if we can make it global variable after it generated from the mainFunc() then every other function can access it.
we cant edit global variable value from function right?
You can define a variable outside the scope of both of these methods that is accessible from each.
function mainFunc(){
window.x = 1;
}
function doMatch(){
var tot = x + 1;
}

can a function reference itself in javascript?

Suppose we define a function that simply increments its input by some stored value dd:
var obj={}
obj.dd=1
obj.f=function(x){
return x+this.dd
}
Alternatively you could create a closure for dd as follows but this would create a static increment as opposed to one that could be altered later:
var dd=1
var f=function(x){
return x+dd
}
We could alternatively store dd in the function itself:
var obj={}
obj.f=function(x){
return x+this.f.dd
}
obj.f.dd=1
I am curious as to whether it is possible for a function to retrieve a variable attached to itself without going through a parent object, something like a self keyword that would refer to the function itself and would allow the following:
var f=function(x){
return x+self.dd
}
f.dd=1
I know it is unnecessary to do such a thing but I think it would be cool if you could.
You can give function literals a name:
var f = function me(x) {
return x + me.dd;
};
f.dd = 1;
This doesn’t work properly in older versions of IE/JScript, though, as me and f don’t reference the same object. The (deprecated and not usable in strict mode) alternative is arguments.callee:
var f = function(x) {
return x + arguments.callee.dd;
};
f.dd = 1;
Also, your note about the closure isn’t quite right; it can be altered later, even through another function:
var dd = 1;
var f = function(x) {
return x + dd;
};
var setdd = function(_dd) {
dd = _dd;
};
A function is an object. If you reference the var holding the function:
var f = function (x) {
return x + f.dd
};
f.dd = 1;
alert(f(1));
result: 2
If the function is named, you can do the same:
function foo(x) {
return x + foo.dd;
}
foo.dd = 1;
alert(foo(1));
result: 2

Generated functions keep reference to variable instead of value replacement?

I have a question to a specific behavior of javascript:
I have an object which I want to fill with generated functions. Each function contains a variable which is changed during the loop of function generation.
My problem is that the variable does not get replaced when assigning the function to the object. Instead the reference to the variable stays in the function and when executing the function only the last value of the variable is remembered.
Here is a minimal example (also on jsfiddle: http://jsfiddle.net/2FN6K/):
var obj = {};
for (var i = 0; i < 10; i++){
var nr = i;
obj[i] = function(){
console.log("result: " + nr);
}
}
for (var x = 0; x < 10; x++){
obj[x]();
}
The second loop executes all generated functions and all print a 9 as result. But i want that they print the value which the variable had at the time of generation (0, 1, 2, ...).
Is there a way to do this? Thanks in advance.
One approach is to call a function that returns a function:
function makeFunc(i) {
return function() {
console.log("result: " + i);
}
}
for (...) {
obj[i] = makeFunc(i);
}
Another approach is the immediately invoked function expression:
for (i = 0; ...; ...) {
(function(i) {
obj[i] = function() {
console.log("result: " + i);
}
})(i);
}
where in the latter case the (function(i) ... )(i) results in a permanent binding of i passed as a parameter to the outer function within the scope of the inner function
The problem is that all the functions you create are sharing a reference to the same nr variable. When you call them they fetch the value using that reference and therefore all of them get the same result.
Solve it like this:
for (var i = 0; i < 10; i++){
(function(nr) {
obj[nr] = function(){
console.log("result: " + nr);
}
})(i);
}
Your surmise is correct, and yes, there's a solution:
obj[i] = function( nr_copy ) {
return function() {
console.log("result: " + nr_copy);
};
}( nr );
JavaScript variables are scoped at the function level, unlike some other block-structured languages. That is, the fact that you declare "nr" inside the for loop doesn't make it "local" to that block — the effect is precisely the same as if you'd declared it at the top of the function.
By introducing another function scope with that anonymous function, you make a new copy of the value of "nr", which is then privately accessible to the actual function that's returned. Each of those functions will have it's own copy of the value of "nr" as it stood when that slot of the "obj" array was initialized.
what you want is to create a closure for every function you create.
Yet, the var(s) have not a block scope, so your code is the same as :
var obj = {};
var i;
var nr;
for (i = 0; i < 10; i++){
nr = i;
obj[i] = function(){
console.log("result: " + nr);
}
}
which hopefully makes it more obvious all functions will refer to the very same 'nr' var.
What you want to do implies creating a new scope each time, which might be done using bind, but let's stick to your original intent and build a new closure each time with a lambda :
var obj = {};
for (var i = 0; i < 10; i++) {
obj[i] = (function(){
var this_nr = i;
return function(){
console.log("result: " + this_nr);
}
}() );
}

Categories