Not being able to reference a variable from outside the loop - javascript

Iam not able to reference a variable from outside the loop in the following function. I want to use the value inside the function itself but the scope doesnt seem to allow it.
function coinOnTheTable(m, k, board) {
for (var i = 0; i < board.length; i++) {
for (var j = 0; j < m; j++) {
if (board[i][j] === "*") {
const a = `${i}${j}`;
return a;
}
}
}
}
Works, While
function coinOnTheTable(m, k, board) {
for (var i = 0; i < board.length; i++) {
for (var j = 0; j < m; j++) {
if (board[i][j] === "*") {
const a = `${i}${j}`;
}
}
}
return a;
}
gives an error
return a;
^
ReferenceError: a is not defined

That's because a variable defined as const or let has "block scope". That means it is only visible inside the nearest set of curly braces. So:
function foo() {
const foo = 'foo-string';
if(1) {
const bar = 'bar-string';
console.log(bar); // This is fine
}
console.log(foo); // This is also fine
console.log(bar); // Error!
}
To solve your problem, you need to define your variable outside of the block defined by the nested for loop. So:
function coinOnTheTable(m, k, board) {
let a;
for(var i = 0; i < board.length; i++){
for(var j = 0; j < m; j++){
if(board[i][j] === "*"){
a = `${i}${j}`;
}
}
}
return a;
}
Note, the reason it changes from const to let is because const variables cannot be reassigned, but since you want to declare it as undefined (at the start of the function, then assign a string to it (inside the loop), you need to be able to reassign it.

make a function scope:
function coinOnTheTable(m, k, board) {
let a;
for(var i=0;i<board.length;i++){
for(var j=0;j<m;j++){
if(board[i][j]==="*"){
const a=`${i}${j}`;
}
}
}
return a;
}

Related

How can I use variable in method function? (JavaScript)

let newArr = 0;
function solution(arr) {
for (let i = 0; i < arr.length; i++) {
newArr += arr[i];
}
}
console.log(solution([1,2,3,4])) //undefined ;
I want to add all of arrays. But error says, 'newArr' is assigned a value but never used.
How can I use variable in method function?
I tried to declare variable in method.
function solution(arr) {
for (let i = 0; i < arr.length; i++) {
let newArr = 0;
newArr += arr[i];
}
}
Of course it didn't work :(
Minimal changes, return newArr, though this isn't the cleanest solution
let newArr = 0;
function solution(arr) {
for (let i = 0; i < arr.length; i++) {
newArr += arr[i];
}
return newArr // add this line
}
console.log(solution([1,2,3,4]))
Alternatively, call the function (without a return) then output newArr because the function is changing its value. Global variables like this are generally not good practice, but it does depend on the situation
let newArr = 0;
function solution(arr) {
for (let i = 0; i < arr.length; i++) {
newArr += arr[i];
}
}
solution([1,2,3,4]) // call function
console.log(newArr) // output the value
Define newArr in the function and return it
function solution(arr) {
let newArr = 0; // define local variable
for (let i = 0; i < arr.length; i++) {
newArr += arr[i];
}
return newArr // return value
}
console.log(solution([1, 2, 3, 4]))
// console.log(newArr) // would be undefined
Hi #Josh Yeom,
The newArr variable is declared inside the solution function. So, guess what, it is only accessible within that function. The Value of newArr outside the function you can't use, because it's not in the same scope.
It's a concept of lexical scoping.
The scope of a variable is determined by its position in the code. Variables that are declared inside a block of code, such as a function or loop, are only accessible within that block. This is known as lexical scoping.
Or in other words.
Lexical scoping is a way of determining the accessibility of variables in a program based on their position in the code. It is a fundamental concept in many programming languages, including JavaScript.
In your case, need to do your code like this.
function solution(arr) {
let newArr = 0;
for (let i = 0; i < arr.length; i++) {
newArr += arr[i];
}
return newArr;
}
console.log(solution([1,2,3,4])) // 10
The newArr variable is declared outside the for loop, so it is accessible throughout the function. The value of newArr is then returned from the function using the return statement, and you can access this value by calling the solution function.
Here is a simple example of how lexical scoping works in JavaScript.
let globalVariable = "I am a global variable";
function outerFunction() {
let outerVariable = "I am an outer variable";
function innerFunction() {
let innerVariable = "I am an inner variable";
console.log(innerVariable); // "I am an inner variable"
console.log(outerVariable); // "I am an outer variable"
console.log(globalVariable); // "I am a global variable"
}
console.log(innerVariable); // ReferenceError:innerVariable is not defined
console.log(outerVariable); // "I am an outer variable"
console.log(globalVariable); // "I am a global variable"
}
console.log(innerVariable); // ReferenceError: innerVariable is not defined
console.log(outerVariable); // ReferenceError: outerVariable is not defined
console.log(globalVariable); // "I am a global variable"
That is because your function does not return the calculated value after completion.
let newArr = 0;
function solution(arr) {
for (let i = 0; i < arr.length; i++) {
newArr += arr[i];
}
return newArr;
}
console.log(solution([1,2,3,4]));
function doesn't have return value like you have to check then put console inside that function
For Exa
let newArr = 0;
function solution(arr) {
for (let i = 0; i < arr.length; i++) {
newArr += arr[i];
}
return newArr;
}
console.log(solution([1,2,3,4]))

Using pure function with Javascript object

Suppose I have a code like this:
function example() {
const obj = {};
for (let i = 0; i < 10; i++) {
for (let j = 0; j< 10; j++) {
if (obj[i] == undefined) {
obj[i] = 0;
}
if (obj[j] == undefined) {
obj[j] = 0;
} else {
obj[i] += i;
obj[j] += j;
}
}
}
}
Here you can see:
if (obj[i] == undefined) {
obj[i] = 0;
}
I check if i not in obj I assign the key i inside obj with 0 else I do nothing, I do sample with j.
The code is duplicated and I do not want to repeat my self, it is bad practice so I make another function to apply for i and j like this:
function initObjWithValue(obj, keys) {
for (const key of keys) {
if (obj[key] === undefined) {
obj[key] = 0;
}
}
}
The function is very easy to understand right? It has first parameter as an object and the second parameter is an array of keys to check. Now I can refactor my code like this:
function example() {
const obj = {};
for (let i = 0; i < 10; i++) {
for (let j = 0; j< 10; j++) {
initObjWithValue(obj, [i, j]);
obj[i] += i;
obj[j] += j;
}
}
}
The code is clearer but as you can see in my function initObjWithValue, it mutates obj and I think it is not good. Here is the quote from Wiki page:
In computer programming, a pure function is a function that has the following properties:
Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
And I got stuck at this point, how can I do not repeat my self and I can achieve pure function in this case?
You could instead make initObjectWithValue return a new object, which you can then merge with your current obj. This way, all you're doing is reading from obj, and not mutating it within initObjectWithValue:
function initObjWithValue(obj, keys) {
const tmp = {};
for (const key of keys) {
if (!(key in obj)) {
tmp[key] = 0;
}
}
return tmp;
}
function example() {
const obj = {};
for (let i = 0; i < 10; i++) {
for (let j = 0; j< 10; j++) {
Object.assign(obj, initObjWithValue(obj, [i, j])); // merge the return with current object
obj[i] += i;
obj[j] += j;
}
}
return obj;
}
console.log(example());
Instead of checking
(obj[i] == undefined)
write
(typeof obj[i] == undefined)

accessing local variable outside of for loop

I have a function
$rootScope.getCurrency = function() {
for (var i = 0; i < data.records.length; i++) {
for (var j = 0; j < data.records[i].columns.length; j++
if (data.records[i].columns[j].fieldname == "Currency") {
// Here I want to
// return the values
// if I do something like
return data.records[i].columns[j].value
// the loop exits on the first condition
// and does not iterate over completely. If I put
// return outside of the
// for loops it says i, j are undefined.
// How can I use the value outside of this loop
}
}
}
}
}
I have to use the returned value in my HTML for binding data.
My HTMl looks like:
ng-repeat i in someArray ng-if={{i.type==currency?getCurrency():''}}
Try pushing the values to an array:
$rootScope.getCurrency = function() {
var result = [];
for (var i = 0; i < data.records.length; i++) {
for (var j = 0; j < data.records[i].columns.length; j++
if (data.records[i].columns[j].fieldname == "Currency") {
// Add to array
result.push(data.records[i].columns[j].value);
}
}
}
return result;
}

Cannot set property 'XY' of undefined

I have following code:
var favourites = JSON.parse(localStorage.getItem("favourites"));
Service.all().then(function (multiple) {
var array = [];
for (var i = 0; i < multiple.length; i++) {
for (var j = 0; j < favourites.length; j++) {
if (favourites[j].checked === true) {
if (multiple[i].Name === favourites[j].name) {
Service.getAllBySomething(multiple[i].Id).then(function (resources) {
var arrayOfSomething = [];
for (var k = 0; k < resources.length; k++) {
arrayOfSomething.push(resources[k].ResourceCategoryId);
}
arrayOfSomething = arrayOfSomething .filter(function (elem, pos, arr) {
return arr.indexOf(elem) == pos;
});
multiple[i].existingProperty= arrayOfSomething;
});
array.push(multiple[i]);
}
}
}
}
$scope.vendors = array;
});
My problem is that it says everytime 'Cannot set property existingProperty of undefined'. And I don't know why multiple[i] should be undefined at this line:
multiple[i].existingProperty= arrayOfSomething;
The property exists, I am sure. And it is defined, it is an empty array. And this empty array I want to replace with my made array in the loops.
Where is the fault? How I can fill the existingProperty with my array?
is Service.getAllBySomething asynchronous by any chance? Because in that case, by the time the callback function runs, i (captured in a closure only) has been moved to the end of the array.
Use an additional closure to capture the value of i at the time of dispatching the async call, like this:
Service.getAllBySomething(multiple[i].Id).then(function(i){
return function (resources) {
var arrayOfSomething = [];
for (var k = 0; k < resources.length; k++) {
arrayOfSomething.push(resources[k].ResourceCategoryId);
}
arrayOfSomething = arrayOfSomething .filter(function (elem, pos, arr) {
return arr.indexOf(elem) == pos;
});
multiple[i].existingProperty= arrayOfSomething;
};
}() );
Note the new function receiving i as a param and returning the function you previously used. I'm invoking immediately (an IIFE) to return the function to pass as callback. Inside that function the value of i will be the same as when you dispatch this async call, as it was copied when used as a parameter.

Javascript - Index inside a for reader into a for inside a function, is it possible?

javascript:
for (i = 0; i < n; i++)
{
v = fn(obj);
}
function fn(o)
{
for(i = 0; i < o.length; i++)
{
...
}
}
The first index get modify from second FOR inside the function fn(o);
How is it possible? what's the scope of index?
It doesn't look like you're declaring i as a local variable, so what's happening is that i being treated as a global variable. You need to write the var keyword in order for a variable to become a local variable.
for (var i = 0; i < n; i++)
{
v = fn(obj);
}
function fn(o)
{
for(var i = 0; i < o.length; i++)
{
}
}
I don't see any var so it looks like you're not varing anything, but I'll add those in and answer the question
Is it possible to modify the i in one for loop from another in a different scope?
When using functions in JavaScript, all primitive arguments are passed ByVal and all object arguments are passed ByRef. This also happens when using =.
Therefore, if you want to modify i out-of-scope, you will need to always access it through an Object.
function foo() { // scope this away from fn
for (var c = {i: 0}; c.i < n; c.i++) { // i wrapped in object
v = fn(obj, c); // pass wrapping object into `fn`, too. Now see `fn`
// c.i is now the result of change in `fn`
}
}
function fn(o, c) {
for(var i = 0; i < o.length; i++) {
// ...
}
// make change to c.i
c.i = 0;
}
foo();

Categories