Passing ECMAScript 6 const as Function Argument - javascript

I've been reading a lot about ES6 lately and decied to give it a try (using Babel). I'm a little confused with new variable declarations let and const.
I understood how scope differs from var; and that const is a permanent reference to a value (and not a constant value itself!).
Q: What if I pass const variable to a function call? Will the receiving function be able to change the value / reference? Why? Why not?

The semantics of a parameter being passed to a function is completely independent of how that parameter was declared (whether using var, let, or const). What is passed to the function is merely some value. The receiving function has no visibility into how or where the value was derived, including, if it is a variable, how that variable was declared. It merely sees the value that was passed in. The new let and const keywords have no relevance to this behavior.
It is the source of some confusion that given the value of an array or object, that array or object can be manipulated. So I can do the following:
const a = {};
a.x = 1;
const in the above makes a itself a constant within its scope, so it cannot be re-declared or re-assigned, but it in no way prevents the internal structure of a from being changed, in this case by adding a property x.
Similarly, in a parameter-passing context:
function func(obj) { obj.x = 1; }
const a = {};
func(a);
Here, func receives the value of a as obj, but with that value it may access/change the internals of the object.
Of possible interest: How to make function parameter constant in JavaScript?.

As you can see here and here that the const declaration creates a read-only named constant i.e. not a named reference.
Now, if you pass a const to a function you are actually creating a new scope:
You are passing the const "by value" and the local function variable will get the value of the const and not the reference to it as in any non immutable object (like strings).
You will be able to change the local var but not the original const.

When you pass a variable with a primitive type (string, number, etc.) as argument, you pass the variable by value. When it's a reference to an object or array, you pass by reference, but the function argument is another variable, not const (mutable), that has the same reference.
It means that the argument variable has the same reference and can make changes (like adding or removing data in the array) that will impact the original variable, but if the argument variable changes it's reference (like argument = {}), the changes will not reflect to the original variable (even if the original one is not const).
Example:
const str = 'string';
function changeToNumber(argument) {
argument = 10;
}
changeToNumber(str);
console.log(str); // 'string'
const obj = { prop: 1 };
let notConstObj = { prop: 1 };
function changeToArray(argument) {
argument = [10];
}
changeToArray(obj);
console.log(obj); // '{ prop: 1 }'
changeToArray(notConstObj);
console.log(notConstObj); // '{ prop: 1 }'
function modifyObj(argument) {
argument.prop2 = 10;
}
modifyObj(obj);
console.log(obj); // '{ prop: 1, prop2: 10 }'

Related

Why is it not possible to set null to an Object passed by reference in JavaScript? [duplicate]

This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 2 years ago.
I don't know why in the following example it is not possible to define null to the object, however it is possible to add properties to it
function callByReference(myFunc) {
myFunc.b = 2;
myFunc = null; // this not set null to Object arg
// myFunc.b = 2; //If I set it after, throws error
}
let customObj = {
a: 1
};
console.log("Before call by reference method");
console.log(customObj);
callByReference(customObj);
console.log("After call by reference method");
console.log(customObj);
Even if I set it null first and then adding a property throws an error;
I don't understand this behavior well. Is there any reason? maybe I'm not understanding how javascript works when passing by reference a argument
The way Javascript works, every variable name is essentially a pointer (or reference) to some value. When you create a new variable by referencing an old object, or when you call a function, you're basically copying the pointer. Eg:
const fn = (param) => {
// ...
};
const obj = {};
const obj2 = obj;
fn(obj);
Above, obj2 and param both point to the empty object that was initially created in obj, you might think of it as:
obj: MemAddress1234
obj2: MemAddress1234
param: MemAddress1234
Whenever you use the = assignment operator, you reassign the binding for that variable name, but doing so doesn't affect any other variables that may have pointed at the same thing:
param = null;
results in something like
obj: MemAddress1234
obj2: MemAddress1234
param: MemAddress0
At least, that's one way to look at it. The link between obj and the empty object, and the link between obj2 and the empty object, remain unaffected, because it's only the param variable name was reassigned.
Reassigning a variable by itself will almost never have any side-effects on anything else. The two exceptions are with arguments in sloppy mode:
function foo(a, b) {
console.log(arguments);
a = 5;
console.log(arguments);
}
foo(1, 2);
and with mutable variables exported by ES6 modules.
This is the way the JavaScript works:
Parameter is always pass by value, but when a variable refers to an object, the "value" is a reference to the object.
Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object (but if you change a property a property in underlying object is changed too).
First, you created a customObj object, that is stored somewhere in the memory.
Then you have a function with an argument function callByReference(myFunc).
If you call the function with your object callByReference(customObj) it will assign a reference pointing at customObj to the myFunc. So now myFunc points to the same place in memory as customObj.
Now, if you modify something inside myFunc, you are changing the same memory as customObj - that is why myFunc.b = 2; will modify customObj. But if you assign something new to the myFunc, you are modifying where it is pointing, not what is inside. So myFunc = null; is like telling "now myFunc points to null memory", but customObj is still pointing to the same part of the memory, so the data is the same.

JavaScript objects defined in different ways

I'm fairly new to JavaScript and have a question regarding how objects are defined in below code snippet.
In the first instance domStrings object is defined as domStrings= and in the second instance the returning object is defined as getinput:function() what is the difference? And why if I change the returning object as getinput=function, it doesn't work? Please help me understand.
var UIcontroller = (function() {
var domStrings = {
inputType: '.add__type',
inputDescription: '.add__description',
inputValue: '.add__value',
addButton: '.add__btn'
}
return {
getinput: function() {
return {
type: document.querySelector(domStrings.inputType).value,
description: document.querySelector(domStrings.inputDescription).value,
value: document.querySelector(domStrings.inputValue).value
};
},
getDomStrings: function() {
return domStrings;
}
}
})();
var domStrings is an object, objects have keys and values. inputType, inputDescription, inputValue, addButton are the keys and to the right of them are their values. You can access these by doing domStrings.inputType etc..
your function here is returning another object return {}
so getinput is actually a key for that object that's why it's defined like that
What you are looking at is called an immediately invoked function expression (or IIFE, pronounced "iffy"). It is a work around for (ECMAScript 5) JavaScript to avoid hoisting and create closures.
In your example the variable domString is being assigned using the equals sign and the part on the right is something called an object literal and uses object literal syntax. The two functions being returned in the return statement are being declared as properties no different than they are in the object literal domStrings inputType: for example. The difference is that the value of properties in the return statement object literal are functions rather than strings. Variables and object properties in JavaScript can contain functions as their values.
In your example: domStrings is a private property of the UIcontroller function and is not accessible from anywhere else but inside the UIcontroller function. It exposes two public functions: getDomStrings and getinput and returns them to be used by callers upon instantiation.
Those two methods have access to domStrings but outside of the UIcontroller function nothing else does unless you also return a reference to domString in the return statement.
You could call UIcontroller.getDomStrings() and UIcontroller.getinput() but you can not call UIcontroller.domStrings. Returning domStrings in the return statement would make it a public property of UIcontroller which anyone could change anywhere.
Hope that helps. Does that answer it for you?
Happy coding!!!
This is an assignment and a declaration of two things:
var domStrings = {
inputType: '.add__type',
inputDescription: '.add__description',
inputValue: '.add__value',
addButton: '.add__btn'
}
The variable domstrings is declared var domStrings and assigned =.
The variable now points to a location in memory. In that location in memory is an object that just got created.
An object in JavaScript is a dictionary: it is a set of key: value pairs, where the key can be a string or a number (or a Symbol, but don't worry about that for now).
The syntax for an object declaration is: { 'key': 'value' .... }.
The value can be any of the JS types - so, basically, a string, a number, void, a function, or another object.
You can point another variable at the same object in memory:
var a = domStrings;
a.inputType /// '.add__type'
If I now assign something else to domStrings:
domStrings = "nope"
domStrings is now pointing to a different location in memory:
domStrings.inputType // undefined - "nope" doesn't have a property inputType
a is still pointing to the object:
a.inputType // '.add__type'
So that statement does more than one thing. It declares a variable domStrings, it creates an object in memory, and it assigns the object to domStrings so that domStrings is a reference to the object.
Does that make that part clearer?
The second part:
What you are looking at there is called a closure. It is an IIFE - "Immediately Invoked Function Execution" - an immediately executing function that creates something like the singularity around a black hole. All of the internal machinery inside that function closure can see what's in there, but the value of UIController from outside is:
{
getinput:() => {...},
getDomStrings: () => domstrings
}
The getDomStrings function inside the UIController can see the domstrings variable, and pass a pointer to it back to code outside, but it is the only way anything outside the closure can access it.
The getInput function can also see it, and uses it to calculate the object that it returns when it is called.
So you can share code/data between functions inside a closure, but the only way anything outside the closure can see it is if you pass a reference out like getDomStrings does.
This is not very safe, because something outside this closure can call getDomStrings and get a reference to the object. It could then change the values in the object, which will change the behaviour of the getInput function in unpredictable ways.
It looks like the author wanted people to be able to read it that object, but not access it to modify it - in which case the way to do that is to return a copy of the object. That gives the caller an object with the same values, but not in the same memory location. Changing the copy will not change the object inside the closure.
If that wasn't their intention (making it read-only), they may have wanted the interface to that closure to have two functions instead of a function and an object.
I think it is the first, because it has a get but not a corresponding set method.
Because an object is a location in memory, and objects can be nested, copying an object is not trivial. You have to make a copy of all the objects inside it.
Check this out:
const a = {z: 3, k: {a: 3}}
const b = {...a} // "Spread" the keys of a onto b, a "shallow copy"
> b
{ z: 3, k: { a: 3 } } // looks b is a copy of a
> b.k.a = 4 // change a "deep value" of b
> b
{ z: 3, k: { a: 4 } }
> a
{ z: 3, k: { a: 4 } } // the object in a has changed!
> b.z = 2 // change a shallow property of b
> b
{ z: 2, k: { a: 4 } } // b has changed
> a
{ z: 3, k: { a: 4 } } // a has not
What happened here is that the objects a and b are in different memory locations. However, each of these objects has a property k that points to another location, and they point to the same location!
We can check this:
> a == b
false
> a.k === b.k
true // !
So returning domStrings from getDomStrings actually allows code outside this controller to change its behaviour.
Returning a spread would work in this case, because domStrings has no keys that have object references assigned to them.
I would write that as:
getDomStrings: function() {
return {...domStrings};
}
That returns a copy that has the same values in it, so other parts of the program can use them to look things up, make decisions, or select things; but that copy cannot be used to mess with what's inside the closure.
There you go, the lesson on object references in JS that you didn't ask for. You're Welcome!

JavaScript setting value to variable properties on a function call

I found that there are these two ways that a variable property value can be updated on a function call
Example 1:
function bar( arg ) {
return arg + 1;
}
var foo = {
num: 1
};
foo.num = bar( foo.num );
console.log( foo.num );
Example 2:
function bar( arg ) {
arg.num = arg.num + 1;
}
var foo = {
num: 1
};
bar( foo );
console.log( foo.num );
I want to know what are the proper naming convention for each of the method calls.
Also can anyone explain, how it is possible to update the original variable value inside a closed function operation as shown in example 2?
Primitive parameters (such as a number) are passed to functions by
value; the value is passed to the function, but if the function
changes the value of the parameter, this change is not reflected
globally or in the calling function.
If you pass an object (i.e. a non-primitive value, such as Array or a
user-defined object) as a parameter and the function changes the
object's properties, that change is visible outside the function.
Source : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
Well in javascript objects are passed by reference so when you pass a object to a function you're passing it's memory reference not a copy.
So when you update value in the function it updates the value at reference.
function bar(arg) {
arg.num = arg.num + 1;
}
var foo = {
num: 1
};
bar(foo);
console.log(foo.num);
When you pass a primitive value it is passed by value. It passes a copy of value so whatever changes you do in close function will not affect the original value.
function bar(arg) {
arg = arg + 1;
}
var foo = 1
bar(foo);
console.log(foo);
I want to know what are the proper naming convention for each of the methods.
There are no naming conventions for functions (I would only call them methods if they are directly associated to an object), except thar the name is camelCase. However there is a convention in functional programming that functions that return something are pure (they do not change anything, but just return something new, like your first function), and functions that return nothing are impure, they change something. Wether you strictly follow that pattern depends on your codingstyle, I follow that often but not always. It is also a bit harder in JS as JS is not typed.
also can anyone explain, how it is possible to update the original variable value inside a closed function operation as shown in example 2?
It is impossible. If you pass a number, it is passed as a value, you have no way to find out where that number belongs to. Thats a good thing as you can always keep track which function is able to mutate an object. bar(foo) is, bar(foo.num) is not.

Why is my constant not pointing to new value

If i am not wrong, the pointer that the variable name is using cannot change in memory, but the thing the variable points to might change.
let name = "google";
const foo = name;
console.log(foo); //prints google
name = "yahoo";
console.log(foo); //prints google again instead of yahoo
Should it not print yahoo, as the variable name's value has been changed.. Can anyone explain me this.
Another example, where its changes...
const foo = [];
foo.push("test");
console.log(foo); // outputs ["test"]
I am getting confused here, can anyone explain me this.
Your first example uses an immutable string and the second uses a mutable object.
JS strings are immutable after being declared or created, so foo is not a reference to name's value, it points to the string. You're not changing the strings, you're pointing to a different one.
The array variable points to the object and continues pointing to the same object after it's been mutated. You're still pointing to the same object, however, since const is not deep.
This also highlights a common misunderstanding with JS' const, which functions more like Java's final than C++'s const. You are declaring a variable as const, not an instance of the object, so it only prevents you from reassigning to the variable, it does not prevent you from mutating the underlying object.
From MDN:
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned.
This means that you can change the value assigned to a const, say by changing array or object, but cannot assign a new value to the const variable. E.g.:
Valid:
const a = [];
a.push(5);
console.log(a);
const b = {};
b['foo'] = 'bar';
console.log(b);
Invalid: This will throw error
const a = [];
a = [5];
console.log(a);
const b = {};
b = {'foo': 'bar'};
console.log(b);

Javascript passing object to function

Quick question on Javascript to which I can't find a clear concise answer.
I'm building an app that's way ahead of anything I've done before and involves multiple classes being instantiated. These objects are then passed into a processing class that checks user inputs, draws onto canvas and updates the objects that it has been passed.
I am wondering, how does JavaScript handle passing objects to functions? Am I passing a copy of the object, or am I passing a reference to the object?
So if my controller class alters one of the objects variables, is that changed everywhere or just in the object that that controller sees?
Sorry for such a simple, possibly easily testable question but I'm not even sure if I'm making a class correctly at this point thanks to errors piling up.
When passing in a primitive type variable like a string or a number, the value is passed in by value. This means that any changes to that variable while in the function are completely separate from anything that happens outside the function.
function myfunction(x)
{
// x is equal to 4
x = 5;
// x is now equal to 5
}
var x = 4;
alert(x); // x is equal to 4
myfunction(x);
alert(x); // x is still equal to 4
Passing in an object, however, passes it in by reference. In this case, any property of that object is accessible within the function
function myobject()
{
this.value = 5;
}
var o = new myobject();
alert(o.value); // o.value = 5
function objectchanger(fnc)
{
fnc.value = 6;
}
objectchanger(o);
alert(o.value); // o.value is now equal to 6
As well described in https://stackoverflow.com/a/5314911/636348, in JavaScript it's always pass by value, but for objects the value of the variable is a reference.
So, it's not a pure pass by reference. Here's an example to understand this concept:
E.g.:
x = {member:"foo"}
If you change the object with another object inside a function, you won't get the new object outside the function scope because you just create another object. The original reference is still bound to the original object:
function changeObject(x) {
x = {member:"bar"};
}
changeObject(x);
alert(x.member)
output: foo
instead, if you alter a member inside a function, the object will be changed:
function changeMember(x) {
x.member = "bar";
}
changeMember(x);
alert(x.member)
output: bar
If you pass in a variable which is pointing to an object, it passes a reference to the object. If you pass in an object literal, then obviously no other class or function will be able to change that object.

Categories