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.
Related
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.
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.
I'm trying to set an object value to a function call using another value (array) as its parameter, however, for some reason the value comes back as undefined, I'm then trying access that value right after that. It's inside an IIFE.
I am unsure why this is happening because to the best of my knowledge the scoping is okay and the value should be initialized and executed by that time?
Here's a simplified example:
(function(){
var minefield = [1,2,3,'M',4,5,6];
function findMachine(minefieldMachine) {
return minefieldMachine === 'M';
}
var terrain = {
start:{initialMachienLocation:minefield.findIndex(findMachine)},
currentMutable:{mutableIndex:terrain.start.initialMachineLocation}//Error: "Uncaught type error cannot read property 'start' of undefined"
//Why isn't the above accessing the value declared in terrain.start.initialMachineLocation through the function call?
}
}());
However, doing this works, out of context from above:
function findMachine(minefield){return minefield === 'M'}
[1,2,3,'M',4,5,6].findIndex(findMachine);
//above returns the proper index value, 3.
This has nothing to do with the function.
What you are attempting to do is, essentially, this:
var foo = {
a: 1,
b: foo.a
}
You need to consider the order of operations.
The object literal constructs an object which is then assigned to the variable foo.
… except that while the object is being constructed, you are trying to read the value of foo. It doesn't have one yet, so this fails.
You need to do this in two steps.
var foo = {
a: 1,
}
foo.b = foo.a;
I have a quick question regarding some code I do not understand:
var anonymousGreet = function(){
console.log('Hi');
}
function log(a){
console.log(a);
}
log(anonymousGreet);
In the code above when I call the function log and pass in the function expression anonymousGreet as a parameter to log. Does that mean the variable "a" in log is pointing to the variable anonymous greet which is then pointing to the function object. Or does a point directly to the function object pointed to by anonymousGreet? I am a little confused if a first points to the variable anonymous greet or does it directly point to the function object pointed to by anonymousGreet. Sorry if this is confusing but any help would be appreciated! Thanks you!
If you come from a C++ background then a simple rationalization is
In Javascript everything is passed by value, references are never used
All passed values are however pointers to objects
For example when you write:
a = b + c;
you should imagine (in C++) something along the lines of
Object *a, *b, *c;
a = new Number(b->numericValue() + c->numericValue());
(note that however Javascript differently from C++ provides a garbage collector so no explicit delete is ever needed).
This is of course just a simple description of what is the observable behavior (and it was may be the implementation of very first Javascript engines). Today what really happens behind the scenes is much more sophisticated and includes run-time generation of machine code (JIT).
This is the reason for which for example:
function foo(x) {
x[0] = 1;
}
var a = [0];
foo(a); // Will change the content of a[0]
but
function bar(x) {
x = 9;
}
var b = 0;
bar(b); // Will *NOT* change the content of b
Yes, if you check a===anonymousGreet, the result is true. All primitive values are passed by value, but objects are passed by reference in Javascript.
var anonymousGreet = function(){
console.log('Hi');
}
function log(a){
console.log(a === anonymousGreet); //true
console.log(a);
}
log(anonymousGreet);
As a matter of terminology, and to avoid confusion, I would avoid the use of the word "pointer". It's too easy to get confused when using the word "pointer". Sometimes "A pointing to B" can mean that A is a kind of alias for B. Or that B can be modified through A. Or A can point to B which points to C; what does that mean?
IMO it is clearer to use the terminology that in JavaScript a variable holds a value. That's it. It holds a value. It does not point to anything, it does not refer to anything, it holds a value.
However, two variables may hold the same value, such as an empty array []:
var a = [];
var b = a;
Both a and b hold the same value, a particular empty array. We can see that they hold the same value by checking a === b. Since they hold the same value, that value can be manipulated through either one; a.push(1) and b.push(1) do exactly the same thing, because they are both manipulating the value held in common by each. Re-assigning to a merely changes the value that a holds; it does not and cannot affect b, and vice versa. b is not a "pointer" to a, or an alias to a; it is a variable which happens to hold the same value as a.
In other words, a = b does not make a "point" to b. Nor does it copy the value of b and assign it to a. It gives a the value of b, so that a and b now hold the identical value.
The function parameter passing mechanism can be thought of as a particular type of assignment. It makes the formal parameter in the function definition assume, or hold, the value of a parameter specified in the call. When I define a function
function foo(x) { console.log(x); }
and then call it
var y = 42;
foo(y);
the variable/parameter x is assigned the value of the parameter passed in the function call. In other words, x comes to hold the value of y. x does not "point" to y, and it is not a copy of y. It holds the same value as y, which in this case is 42.
Let's take your specific example:
var anonymousGreet = function(){
console.log('Hi');
}
function log(a){
console.log(a);
}
log(anonymousGreet);
In this case, anonymousGreet is a variable which, by virtue of the assignment, holds as its value a particular anonymous function. When you call log(anonymousGreet), the parameter a to the log function is set to hold the value of the parameter in the call, so it now holds the value of anonymousGreet. It does not "point" to the variable anonymousGreet, and any changes to it cannot affect the value of anonymousGreet, nor of course the function which that value represents.
Does that mean the variable a in log is pointing to the variable anonymousGreet which is then pointing to the function object?
No, it means that the variable/parameter a in log holds the value held by anonymousGreet, which is the anonymous function.
Or does a point directly to the function object pointed to by anonymousGreet?
Yes, but not "point to the thing pointed to by", but rather, "holds the value of anonymousGreet, which holds as its value the anonymous function.
This question already has answers here:
prototype: deep scope of "this" to access instance's scope
(5 answers)
Closed 8 years ago.
Given:
var x = function () {
};
x.prototype = {
y: {
z: function () {
console.log(this);
}
}
};
var foo = new x();
foo.y.z();
Why is this logged in the console as y instead of x and how is that possible given y is a literal object without a constructor?
"Why is this logged in the console as y instead of x..."
Because that's how JavaScript works. The this value is set as the object from which the method was invoked. Generally you should keep objects off of the .prototype. They're going to be shared among all instances created using the constructor.
"...and how is that possible given y is a literal object without a constructor?"
It's easy. The this value is not tied to any constructor. It's a dynamic value that is set based on how you invoke a function or method.
There are utilities that let you manually override the natural value that this is set to in an invocation. Using the .call or .apply methods of the Function.prototype to invoke the method is one example
var foo = new x();
foo.y.z.call(foo);
Now this in the z method will be the foo object, because we manually set it by passing it as the first argument to .call.
The .call method sees that it was called as a method of the z method, and so it invokes z for you, but sets the this value of z to whatever you provided as the first argument... in this case the foo object.
But generally you won't use objects as values of the .prototype. The reason is that all instances created from the constructor get an implicit reference to the .prototype of the constructor, so updates to any objects on properties of the .prototype will be observed from all instances.
To make this work, you need y to return the enclosing this.
var x = function () {};
Object.defineProperty(x.prototype, "y", { get: function() { return this; } })
x.prototype.y.z = function () { console.log(this); }
var foo = new x();
foo.y.z(); // x
Whatever is to the left of the . on z() is this. In your question, y returns the object literal: {z:function(){...}}.
var y=Object.create({z: function () { console.log(this); }});
var x=Object.create(y);
y.z();
x.z();
You may use Object.create to create an object instead of using constructor.