I was wondering if there's a way of changing some variable value with the return of some function. A short-hand-way of doing it.
If I want to add some value to a variable and changing it, we do like that:
let numb = 5;
numb *= 2; // Returns 10
But lets say I have a function that return the double of its argument like this:
function double(a) {
return a * 2;
}
let numb = 5;
numb = double(numb); // Short hand of doing this line <----
You need to understand how reference and value parameters work. When you pass in a number or a string to a function that is a value parameter and changing the value of the parameter withing the function has no effect on the variable that was passed in. If the parameter is a reference to an object then changes to properties on that object will then change the variable passed in.
let x = 5;
someFunc(x);
There is no way for someFunc to change x because the value 5 of x was passed into the function, not a reference to x;
let x = { prop: 5 };
someFunc(x);
Now if the body of someFunc changes x.prop then it will also change it to the variable x that was passed in because a reference to an object instance was passed in.
It is the same as assigning variables.
let x = 5;
let y = x;
Now x and y are both 5 but changing y = 6 does not effect x.
let x = { prop: 5 };
let y = x;
Now y is a reference to the same object so y.prop = 6 will change x as well.
All that aside good programming principles and modern functional programming concepts dictate that modifying parameters passed into functions is not good practice.
You could use an arrow key function. Saves a line or two.
const double = a => a * 2;
let numb = 5;
numb = double(numb);
Removing the short hand, the double function would look like
const double = (a) => {
return a * 2
}
Arrow key functions are pretty much the same as a normal function, however they give you more control over the 'this' keyword.
Related
I have a script like this:
function changeValue(x){
x = 30;
}
let a = 3;
changeValue(a);
console.log(a);
The above code outputs 3, but the expected output is 30. Now I'm aware why this is happening, but how do I modify my code so that the changes made do not revert after the changeValue function ends?
I have read that there are no explicit pointers in JS and I don't want to alter the value using the global variable name or by using the object approach. Is there any other way to solve the problem?
Thank you
The best way would be to use return, because x isn't an object, it's just a variable. It is discarded after the function.
Using Return:
function changeValue(x){
return 30;
}
let a = changeValue(3);
changeValue(a);
console.log("Output Is:", a);
In JavaScript, all primitive types (integers, floats, etc) are passed by value, so as other people said, for your specific use case, it's better to return the value like this:
function returnValue(x) {
return x * 10
}
let a = 3;
a = returnValue(a);
console.log(a);
However, if you really want to change the argument and NOT return, you need to do it with pass by reference. As I said above, it's not possible with primitive data types but is possible with objects:
function changeValue(x) {
x.value = x.value * 10;
}
let a = { value: 3 };
changeValue(a);
console.log(a.value);
In the Eloquent Javascript book, in chapter 6 there's the following example:
class Matrix {
constructor(width, height, element = (x, y) => undefined) {
this.width = width;
this.height = height;
this.content = [];
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
this.content[y * width + x] = element(x, y);
}
}
}
//...
}
As you can see the 3rd parameter to the constructor is not just a callback parameter, but actually the implementation of the callback.
At first I thought, maybe the body of the implemented callback function is disregarded but at least the future callbacks used in the constructor will be checked to have the same signature. However, I found that the signatures don't matter as the code below will work:
const test = new Matrix(2, 4, () => console.log('hello'));
So what's the point of implementing callback, it being a parameter of a function? Is just for a reader to infer how many parameters will be passed to the callback?
If you do not specify a third parameter, the default value of element would be (x, y) => undefined.
Please refer to this MDN link. It will give some insight. Hope this helps.
What the example is doing with element is to set a default value. In this case the default value does nothing.
Note that you can also use ()=>{} as default of element, it will work in JavaScript since the language doesn't validate the number of arguments when you call a function (but it may give you a type checking error in TypeScript).
This is a common pattern: instead of using undefined or null, you put a default parameter that does nothing, so in the code you don't need to check if element is defined before calling the function. See: https://en.wikipedia.org/wiki/Null_object_pattern
Some libraries like lodash also include constants like noop defined as en empty function, so you can write the code as:
const noop = ()=>{}
class Matrix {
constructor(width, height, element = noop) {
//...
}
}
Additional information:
The Matrix constructor seems to be initializing a single dimension Array to store the matrix. You can replace that nested for loop with Array.from. Something like:
this.contents = Array.from(
{length: height * width},
n => element(n % width, Math.floor(n/height))
);
I didn't check the math so the example may have index errors. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
The way I understand it, it's simply an optional initializer. If you call it with something like () = > 0, it will initialize your matrix with 0 instead of undefined. (x,y) => x === y ? 1 : 0 would produce an identity matrix. etc ....
(update after reading the chapter)
This is borne out by the sentence following the exemple in the book:
The constructor function takes a width, a height, and an optional element function that will be used to fill in the initial values.
This class has 3 parameters applying to "Constuctor".
The third one is callback function named "element" is optional, and has default value of "(x,y)=>undefined". So if you did not pass third argument when building a new instance of "Matrix" class it will be as default.
if you pass specific function here (for example)
let myMatrix = new Matrix(100,100,(x,y) => x * y);
at this stage
this.content[y * width + x] = element(x, y);
it will returns corresponding values to respective array slots of "this.content" property of your new "Matrix" instance.
So your Matrix will have such "content" property (for example):
myMatrix.content[0] = 0;
myMatrix.content[1] = 0;
...
myMatrix.content[101] = 1;
myMatrix.content[102] = 2;
// and so on
Otherwise if you don't pass any function when creating a new instance, all generated array slots of "this.content" property will be assigned with undefined values because of default property value of
(x, y) => undefined
function swap(x,y){
var t=x;
x=y;
y=t;
}
This won't work. when you swap(a,b), variable a and b get copied into the function and whatever happens in that function doesn't affect the real value of a and b. I want something like this:
(function(){
a=1;
b=2;
function swap(){//something}
swap(a,b);
console.log(a) //2
console.log(b) //1
})()
How to do this?
If you are using the latest version of JavaScript (ES2015), then you can use the new language feature called "destructuring". You don't need a function. It looks like this:
let a = 1;
let b = 2;
// swap!
[b, a] = [a, b];
If you want a function, you can do it like this:
function swap(a, b) {
return [b, a]
}
[a, b] = swap(a, b);
Looking at this code, I kind of prefer the function, though it is a bit superfluous. I like how expressive it is. You aren't left puzzling over what the code does.
You can't. Arguments are passed by value, even in the case of objects. It's just that the value passed for them is a reference to the object.
Basically this means that any arguments you receive have no actual connection to the original variables you passed in except that they may share a reference.
Imagine you've written a and b on a piece of paper. In JS, the only way to share those values with a function is to copy them on to a different piece of paper and hand it to the function. So even if that function scratches out a on the new piece of paper and replaces it with b, it doesn't change what you have written on the original piece of paper.
In short, it is not possible to change the value of a variable which was used as an argument for a function.
As mentioned in the answers above, Arguments are only passed by value. If you really need to achieve the swap, you can use the 2 variables algorithm:
var a = 10, b = 20;
a = a + b;
b = a - b;
a = a - b;
console.log (a+" "+b); // 20 10
you can set a variable outside the scope of the function so you can use it inside the function, this is something you can do:
<head>
<script>var x=0, y=1;</script>
</head>
<script>
function swap()
{
var t = x;
x = y;
y = t;
}
</script>
or even this works
<script>
var x=0; y=1;
function swap(id1, id2)
{
var t = x;
x = y;
y = t;
}
console.log(x+" "+y);
</script>
I used this quite a lot and works fine. the x and y can be taken from any where and will work inside a function no problem.
you can also do
function(id1, id2)
{
x=document.getElementById(id1);
y=document.getElementById(id2);
var t = x.value;
x.value = y.value;
y.value = t;
}
function swap(value) {
value.first = value.first + value.second;
value.second = value.first - value.second;
value.first = value.first - value.second;
}
// declared an object named value which has two keys - first and second corresponding to the first and the second values respectively
var value = {
first: 1,
second: 2
}
console.log(value.first, value.second) // prints 1 2
swap(value);
console.log(value.first, value.second); // prints 2 1
This question already has answers here:
Does JavaScript pass by reference? [duplicate]
(13 answers)
Closed 7 years ago.
Why doesn't this work and is there any way to get it to work?
Im pretty sure it doesn't work because of variable scoping in javascript, but I can't think of any ways to get it to work.
Code
var x = 5;
var z = function(y) { y = 10; };
z(x);
console.log(x) // Outputs 5 instead of 10
var x = 5
var z = function(y) { y = 10; }
console.log(x) // Outputs 5 instead of 10
Where exactly did you changed X? you dont have X and you did not call the function as well.
I assume you wish to do this:
var x = {x: 5}
var z = function(y) { y.x = 10; }
z(x);
console.log(x.x) // Outputs 10
The code is using x as variable on an object instead of a primitive number which is passed by value and not by reference and thus cannot be modified.
Using object you can modify the attributes (properties) of the object
X won't change for a couple reasons. The first is that you are modifying the parameter y inside of the function. If you passed an object this would work as those are passes by reference. It would also work if you changed x directly instead of passing it as an argument.
The second reason is that you never ran the function. You need to call z with z()
What happens when you invoke the function z is that the parameters get initialized and assigned the value you passed in.
So the function might read something like
var y = 5;
y = 10;
and so, the y that is in the scope outside of the function, remains unchanged because this y is actually a whole new y variable just for this function's scope.
var x = 5;
var z = function(y)
{
y = 10;
//assigned value 10 to the function parameter variable y.
//You haven't done x=y or x=10 and so how do you expect the value of x to change?
}
console.log(x) // Outputs 5 instead of 10
Change it to:
var x = 5 ;
var z = function(y)
{
x = 10; //changed value of x to 10
}
console.log(x) // Outputs 10
The problem is not related to vatiable scope at all.Your variable x is global since it is outside the function.
AND YES,you can change it's value inside a function.But the problem with your code was that you never changed the value of x.
If this is what you intended to do:
z(x); //x=5 is passed to the function z
function(y)
{
y=10; //initially the value of y is 5.Since you have passed x.
//Doing y=10 does not change the value of x because y is another variable.The value of x was copied to y and y is not x.
x=y;//You have assigned 10 to x
}
console.log(x); //outputs 10
Changing the value of the function parameter does not change the value of the variable whose value you passed to the function.You are actually passing the value of x to y that is you are passing 5 to y and not the variable itself.
You are not passing the variable reference.You are just passing the value.
Here's the example code I'm struggling with:
function greaterThan(x) {
return function(y) {
return y > x;
};
}
var greaterThanTen = greaterThan(10);
show(greaterThanTen(9));
Is there a way to put it in math terms or follow the flow or something? I don't know why 10 is x and 9 is y.
In the line:
var greaterThanTen = greaterThan(10);
You are assinging the variable x to the value 10 and then you store the function in the greaterThanTen Variable to be called later. this means that:
greaterThanTen = function(y) {
return y > 10;
};
So when you do:
greaterThanTen(9); #y = 9
You are calling:
return 9 > 10;
This function doesn't call a function, it returns a function.
This code is creating a new unary function where the original binary (greater than) operator's right-hand operand is prebound to a specific value.
In lambda calculus this binding is known as currying.
In Javascript the binding happens because the supplied value of the parameter x in greaterThan is permanently retained in the scope of the inner function (or "closure") that is returned.
So, when you call:
var greaterThanTen = greaterThan(10);
what you now have is a new function (named greaterThanTen) which always compares its single parameter to the bound value of 10.
Hence:
greaterThanTen(9);
will return false.
Create greaterThan(10)
Create function:
function(y){return y > x}
return function.
So, when you call greaterThan(10), the function returns a function whose local variable x is set to 10.
var greaterThanTen = greaterThan(10) equals:
var greaterThanTen = function(y){return y > 10};
To finish, greaterThanTen(9) is called, which equals 9 > 10, which is false.
The only thing that greaterThan does is to set a value for x in
function(y) {return (y>x);}
and store the resulting function in a variable name, in this case greaterThanTen, now with the contents
function(y) {return (y>10);}
Calling greaterThanTen(9) is the same as looking at
function(y = 9) {return (y>10);}
which is the same as
function(y = 9) {return (9>10);}
which is false. Hence false is returned.
Edit:
Example of function that returns a function here: http://i.imgur.com/aiHSH.jpg (x and y is switched around in y>x)
Namaste
The greaterThanTen variable represents a function taking one argument and returning a boolean value whether this argument is greater then 10.