Scope of variables inside inline function default parameter [duplicate] - javascript

This question already has an answer here:
Scope of Default function parameters in javascript
(1 answer)
Closed 4 years ago.
ES6 introduced default parameters. I'm trying to understand how inline function default parameters work with this new feature. Specifically how its scoping work.
Take for example the following two functions:
function one(x, f = function (){return x})
{
var x = 5;
console.log([x,f()]);
}
function two(x, f = function (){return x})
{
x = 5;
console.log([x,f()]);
}
one(1);//[5,1]
two(1);//[5,5]
Is it correct to say that, in function one, f keeps it's own closure scope for x in the parameter list, so that when the function redefines x as a new var: var x = 5;, the reference that f has, is not the same as the one inside the function?
If that's the case, is function one equal to function three below:
function three(x,f)
{
var x2 = x;
f = f !== undefined ? f : () => x2;
var x = 5;
console.log([x,f()]); //[5,1]
}
I tried, without luck, to find how this behavior is documented, if someone could point me to the right part of the documentation that would also be great.

You are correct. In both of the top functions x in f refers to the parameter x.
There's some considerations with case 3.
In the third example if f isn't defined and you are returning x2 when calling the function it will be equal to whatever x originally was. When you do x = 5; you aren't changing x2. This is because when you assign x2 = x JavaScript makes a copy not a reference.
Unless the x parameter is passed an array or object x2 will be a copy and not a reference of x.
So if you do three(3) then x2 will always be 3 because you're never changing it.

Related

Javascript Function with String/Object attached to it [duplicate]

This question already has answers here:
Add method to string class
(6 answers)
Closed 4 years ago.
In javascript, I want to write a function which is called as follows:
var x = 'testString'
var y = 'anotherstring'
var z = 0
var result = x.aFunction(y, z)
function aFunction(y, z) {
...
}
This is the first time I am attempting this, my question is how can I get and use the value of x in the function aFunction, without actually referring to the declared variable.
I tried looking for this but I cannot find anything. If there is a post specifically for this that anyone knows about, please let me know.
Thanks
You need to use String.prototype.aFunction so that you can add a custom function aFunction() to the prototype of String such that it can be invoked by a string variable. Also this.toString() inside the prototype function will give you the value of the x variable (calling string)
var x = 'testString'
var y = 'anotherstring'
var z = 0
String.prototype.aFunction = function(y, z){
console.log(this.toString());
return y+z;
}
var result = x.aFunction(y, z);
console.log(result);

How to inject a variable into a function's closure without using "with" or "this"?

Suppose that I have defined a function like following:
const addX = (y) => x + y
It is obvious that the x inside the function body is a free variable.
If I want to specify a value to x after the definition of addX, and keep the principle about not using this and with, is there any possible way?
This is very useful when we are designing an EDSL in JavaScript.
NOTE: I know that we can do some similar thing like following:
const add = (x) => (y) => x + y
const addX = add(1)
But In my case, the definition of addX is already done, so that is not working.
You could assign a value to the global variable and call the function then.
var addX = y => x + y, // global scope
x, // global scope
add = xx => y => { // get all values
x = xx; // assign to global x
return addX(y); // call fn with y and take global x
};
console.log(add(10)(32));

Javascript : What is the difference between these two fat arrow functions? [duplicate]

This question already has an answer here:
Where can I get info on the object parameter syntax for JavaScript functions?
(1 answer)
Closed 5 years ago.
const f = ({x,y})=>{...do something...};
const f = (x,y)=>{...do something...};
What is the difference between these two lines ?
My understanding is both pass "x" and "y" are arguments.
Are both the same then ?
The first one uses destructuring you can use it as
f({x: 0, y: 1})
you pass one object with fields x and y
and then in body you can access fields of object as variables x and y.
In the second one you have to pass 2 variables
f(0, 1)
Bodies can be the same of those functions and they would work analogically
for instance
=> { return x + y; }
but params should be passed in different ways
The first one you're passing an object as a parameter. But I don't think it's a working example. Here is one
class O {
x;
y;
}
const example =(o:O)=>{
//do something
return o.x+o.y;
};
The equivalent is
var example = function example(o) {
//do something
return o.x+o.y;
};
The second one you're passing two parameters the equivalent is
var example2 = function example2(x, y) {
//do something
return 0;
};

JavaScript function expression assigned to a variable (pass by reference or value?) [duplicate]

This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 6 years ago.
I have a doubt about the following codes. I thought that data-type primitives assigned to a variable in JS were passed by value, while objects were passed by reference. If functions are objects in JS, I thought they should be passed by reference, but the following two codes behave as passed by value:
CODE 1
var x = function hello(){ console.log("hello")};
console.log(x);
var y = x;
console.log(y);
x = function bye(){console.log("bye")};
console.log(x);
console.log(y);
OUTPUT
[Function: hello]
[Function: hello]
[Function: bye]
[Function: hello]
CODE 2
In this case I assigned a method to a global variable and the behavior is the same:
var x = {name:"Max",
action: function one(){console.log("one")}
}
var y = x.action;
console.log(y);
x.action = function two(){console.log("two")};
console.log(x.action);
console.log(y);
OUTPUT
[Function: one]
[Function: two]
[Function: one]
I truly appreciate any insight and explanation on this.
From that regard, JavaScript is pass-by-value.
Assigning variable X to variable Y will place the value of X in Y, even if the value of X is a reference to an object.
You can see the "by reference" nature that you're looking for when you modify a deeper property in an object:
var x = { foo: () => "bar"; }
var y = x;
x.foo = () => "baz";
y.foo(); // "baz", and not "bar".
If I were to set x to { foo: () => "baz" }, y.foo() would still result in "bar", because I didn't modify the original object, I replaced it with another.
To clarify, JavaScript does not have var x = &y; or something similar like in PHP.
In this code y won't be reference of x later, x is re-assigned with a new function. If you modify a property in x, y will still be a reference of x then.
The same happens with every object in JS.
You are simply assigning functions to variables, there's nothing tricky in this code and it's working as it should, feel free to ask something more.
Pass by reference/value doesn't matter here as there is no passing involved.
The values that these variable contain is a reference to a function. I think what you're expecting is that y and x are linked somehow after the assignment but the assignment only changes what function y refers to with no further association with x.
First x holds a reference to hello, then y is set to hold a reference to hello, then x is set to contain a reference to bye. So at the end, x contains a reference to bye, and y contains a reference to hello.
This is basically the same as:
var x = "hello";
var y = x;
x = "bye";
console.log(x);
console.log(y);

Will the reference of an object passed into a function as a parameter change?

Why is a.y undefined after I change the reference of a in the function?
var a = { x : 1 };
a = { y : 2 };
function _change(b) {
b = { y : 3 };
return b;
}
_change(a);
document.write(a.y); // undefined
document.write(a.x); //1
And the below code behaves differently
var a = {x:1};
var b={y:1};
b=a;
a.x //undefined
a.y //1
Why?
Because you're totally changing the a object {x:1} with {y:2} so there's no x property in a object.
What I think is you need to use like this:
var a = {x:1};
a.y = 2;//assign y = 2 in a oject.
So, do the same manner in your change function.
First Block
This is what I get by running the code line by line:
var a = {x:1}; // <-- sets a to the object {x:1}
a = {y:2}; // <-- sets a to the object {y:2}, so it no longer has a.x = 1
function _change(b)
{
b= { y:3};
return b;
}
_change(a); // <-- this doesn't change a, it returns {y: 3} but it is not used
document.write(a.y); // 2 actually
document.write(a.x); // undefined
Let's try to understand it...
var a = {x:1};
There you declare the variable a, you create an object {x:1}, and set a to that object.
a = {y:2};
There you create a new object {y:2} and set a to it. So a no longer has the first object.
So... when you ask for a.y it has 2, and when you ask for a.x it is undefined because the object {y:2} doesn't have x. Remember that you replaced the object of the variable a from being {x:1} to {y:2}.
Instead you can add fields on the fly, like this:
var a = {x:1}; // <-- sets a to the object {x:1}
a.y = 2; // <-- Add a field y to the object of the variable a, it has the value 2
function _change(b)
{
b.y = 3; // <-- actually modify the object, now the field y has value 3
return b;
}
_change(a);
document.write(a.y); // 3
document.write(a.x); // 1
Second Block
Again, I get a different result than you... I wonder where are you running your code.
var a = {x:1}; // <-- sets a to the object {x:1}
var b={y:1}; // <-- sets b to the object {y:1}
b=a; // <-- now sets b to the object {x:1} - nobody has {y:1} anymore
document.write(a.x); // 1 actually
document.write(a.y); // undefined
Ok, so when you say b=a you are making the variable b to point to the same object as the variable a. By doing so, the variable b no longer points to the object {x:1}... which is irrelevant because you are not using the variable b anyway.
The variable a had {x:1} all along, and you can see it doesn't have any field y defined.
It seems to be that you believe that assigning an object somehow fuses the objects, resulting in both sides having a combination of the fields... if you intend to do that, you may be interested in How can I merge properties of two JavaScript objects dynamically?.
You need to break this down and understand the variables in different lexical scopes.
a in the global lexical scope:
var a = {x:1};
a = {y:2};
The above initialization would resolve to:
a = {y:2};
//hence at this global lexical scope
//`lexicalscope = {"a":{y:2}};`
Now, let us see the variables inside the lexical scope of the function:
function _change(b){
// at the function's `lexicalEnvironment = {"b":{y:2}}`
b= { y:3};
// at this point `lexicalEnvironment = {"b":{y:3}}`
return b; //returned {y:3}.
}
When the function is invoked with a as its parameter.
_change(a); // obtained {y:3} but not captured.
I would love to include the beautiful explanation for why the value of a does not change outside the scope of the function in this answer here, but, do not want to duplicate the original answer. Would like to share the relevant part though,
In practical terms, this means that if you change the parameter itself (as with a),
that won't affect the item that was fed
into the parameter. But if you change the INTERNALS of the parameter, such as b.y = 3,
that will propagate back up.
Again, printing their values in the global lexical scope.
console.log(a.y); // still in the global lexical environment a.y = 2;
console.log(a.x); // `a.x` is undefined in the global Lexical Environment.

Categories

Resources