Javascript object passed in a function but apparently passed by value - javascript

As javascript objects are passesd by reference then why console.log(obj1.a) is showing 1 instead of 7. As function is changing value to 7.
obj1 = {
a: 1
}
obj2 = {
a: 1
}
function c(d) {
console.log('d bef ', typeof d)
if (typeof d === 'object'){
d = obj2
obj2.a = 7
console.log ('d.a', d.a)
}
}
c(obj1)
console.log(obj1.a)

You seem confused by two different concepts.
In JS, objects ARE passed by references, but variable are not.
What does it means is that :
//WHen you declare your VARIABLE, you assign it a REFERENCE to a new object :
const something = { property : 'foo' };
//Something now is a variable whose value is a REFERENCE to an object, not the object itself.
function success(obj){
obj.property = 'bar';
}
function fail(obj){
obj = { property : 'bar' }:
}
//When you call fail :
fail(something);
console.log(something.property); //will print foo
//When you call success :
success(something);
console.log(something.property); //will print bar
In success function above, you access the object by reference through the function argument and you change its property. Because when you call success, the variable something pass its reference to the object by value. So, the argument of success (obj) has for value the reference to the object.
in fail, you replace the reference to the object by a reference to another object.
To be clear : the something variable is passed by value. But this value is a reference to an object.
Thus, you can change object properties through this reference, but you can't change the something variable value by assigning a new value to the function's parameter obj.

By passing the data as a parameter, you pass the object value but not the reference, So, you have a new object with a new reference, just scoped for the function.
This is a simpler example.
// The pet variable have the referance of the { type: 'cat' } object.
let pet = { type: 'cat' }
// p is a copy of the pet variable but not have the same referance.
const changeThePet = (p) => {
p = { type: 'dog' }
}
// here you pass the pet variable
changeThePet(pet)
console.log(pet)
p will hold the value of the pet but they aren't the same variable or same referance

Related

JavaScript: How is Object implemented such that new Object({}) and Object({}) are the same

In JavaScript, I can write:
x = new Object({ a: 3 })
and I will have x = { a: 3 }
Similarly, I can write
x = Object({ a: 3 })
and I will have x = { a: 3 } again.
My question is: How is Object implemented to satisfy both these ways of calling it? In the first scenario, it will receive a fresh this, while in the second it will receive the global object.
My best guess is something like:
var Object = function(obj) {
var global = (function() { return this; })();
if (global == this) { // I am called as a regular function
// Create a copy of obj, potentially like this
return { ...obj };
} else { // I am called via new
// Copy all fields of obj onto this
// not sure what the best way to do this is.
}
}
The answer is in the specificaton:
When Object function is called with optional argument value, the following steps are taken:
If NewTarget is neither undefined nor the active function, then
Return ? OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%").
If value is null, undefined or not supplied, return ObjectCreate(%ObjectPrototype%).
Return ! ToObject(value).
Step #1 is about what the code should do when the call is happening as part of creating something that inherits from Object, so we can ignore that step for your question.
Step #2 doesn't apply because you're passing in value and it's neither null nor undefined.
So Step #3 is what happens: It uses the ToObject operation to do type conversion to turn value into an object. Since value is already an object, that's a no-op, and the result is the same object you passed in. The new Object part of new Object({a: 1}) is completely unnecessary.
In the first scenario, it will receive a fresh this, while in the second it will receive the global object.
As you can see from the spec steps above, Object doesn't use this at all.
I think it is something like
function Object(obj) {
If (this instanceof Object) {
return Object.assign(this, ...obj)
}
return new Object(obj);
}
It's simple as that
function Object(obj) {
return obj;
}
When you call it as function it inherits its parent's scope that is window.
Buy when you initialize it as a class, the function itself is the constructor that has its own scope this.
And it's not creating a new instance with copied properties as you can see in this example:
var a = {a : 3};
var b = new Object(a);
var c = Object(a);
console.log(a === b);
console.log(a === c);
As #user2357112 specified that it's not that simple here is a more close to Object functionality:
function Object(value) {
if (typeof value === 'number') {
return new Number(value);
}
if (typeof value === 'string') {
return new String(value);
}
if (value === null || value === undefined) {
return {};
}
return value
}
var a = new Object(undefined);
console.log(new Object(1));
console.log(new Object('sad'));
console.log(new Object([]));
console.log(new Object({}));
console.log(new Object(null));
console.log(new Object());

How to change a object by function

In one task I have to change a object by deliver it to a function. it is almost like this:
function change(obj) {
return {
fn1: function() {
obj['three'] = 3;
},
fn2: function() {
obj = {'four':4};
}
};
}
var obj = {'one':1,'two':2};
console.log(obj); // output 'Object {one=1, two=2}'
var temp = change(obj);
temp.fn1();
console.log(obj); // output 'Object { one=1, two=2, three=3}'
temp.fn2();
console.log(obj); // output 'Object { one=1, two=2, three=3}'
fn1 is for changing one of the object's value. As you can see, it intends to set obj[three] to 3 and it works well.
fn2 is for replacing the object of another one. The obj should only contain 'four':4 after the execution。 however it didn't work.
Then I check the value of the obj inside fn2:
...
fn2: function() {
console.log('before fn2',obj);
obj = {'four':4};
console.log('after fn2', obj);
}
};
...
The output is:
'before fn2 Object{one=1,two=2,three=3}'
'after fn2 Object{four=4}'
So it did work inside the fn2. I get confused that fn2 fails while fn1 works. How to fix it?
In JavaScript, arguments are passed by value, though that value often has pointer-like semantics. When you run obj['three'] = 3;, you are not rebinding the variable obj; you are merely changing a property of the object that obj currently holds. On the other hand, when you reassign obj, you are changing the variable obj, not the object that the variable used to hold. You cannot achieve your desired semantics in JavaScript; the best you can do would be to delete all properties of obj and copy over whatever properties you want to be on it.

Using 'this' to make values in object

var obj = {
name : 'object',
itis : this.name,
}
why is itis undefined? When I look at the values of the object itis value is blank. Thank-you.
The code
var obj = { name: 'object';
itis: this.name };
is perfectly equivalent to
var obj = {};
obj.name = 'object';
obj.itis = this.name;
in other words the this refer to the current this of the external scope and has nothing to do with the newly created object.
Things are different with
var obj = {};
obj.name = 'object';
obj.itisf = function(){ return this.name; }
console.log(obj.itisf()); // Shows "object"
and it happens because this, when executing the function, will become the object.
A simple rationalization is that when you call a function right after getting it from an object using . the this in that function will become the object. The rule implies also that in Javascript:
obj.f();
and
var ff = obj.f;
ff();
to not do the same thing, because in the first case only during the execution of the code in f the value of this will be the object. In the second case instead this will be the global object.
this is defined by the scope where it appears. So, you can't use this the way you want in an object literal, because the object literal doesn't have its own scope.
this has the meaning given to it by the current scope (i.e., the global scope or that of a function or method). You can do this:
var obj = {
name : 'object',
itis : 'object'
}
or this:
function Obj() {
this.name = 'object';
this.itis = this.name;
}
var obj = new Obj();
but what you're trying won't work. Here's an example of the problem in action:
function Foo() {
this.name = "My function";
var obj = {
name : 'My literal object',
itis : this.name
}
alert(obj.itis); // "My function"
}
Foo();
The alert shows My function because this is defined in the scope of Foo; obj doesn't have its own scope.
this keyword does not refer to the object even though you use that inside one. It just refers to the thing that initiated the current scope.
this refers to the object obj when you pass this in a function:
var obj = {
name : 'object',
itis : function(){
return this.name;
}
}
obj.itis();//'object'
'this' keyword refers to the current scope and in your case; you're using 'this' inside object literal declaration,and I guess, where 'this' would be referring to the 'Window' object.
if we see syntax wise, there would be no error. But at run time it will be 'Undefined'. Look at the below example
var xyz = {
a: 10,
b: 20,
c: this.a + this.b
};
document.write(xyz.a," and ",xyz.b);
document.write(xyz.c);
// to cross check
document.write(Window.a + Window.b);
// Why NaN ?
document.write( undefined + undefined );

Are all parameters to Javascript functions passed only by value?

If I have a variable like this:
I created something similar to an ENUM like this:
var ContentStatusId = {
All: 0,
Production: 1,
Review: 2,
Draft: 3,
Concept: 4
}
When I call a function like this:
doTask(myParam) {
var a =
}
With doTask(ContentStatusId.All);
Is there any way that I can find out anything about the parameter passed to the function or is it completely passed by value only? Are there any other ways to pass parameters to a function?
In JavaScript all parameters are passed by value.
In the case of a primitive, the value is the primitive value.
function test(arg) {
console.log(arg);
}
test(1);
arg will have the value of 1.
However, if you say
test({});
then arg will contain a value which is a REFERENCE to the object we just created.
Edit to address comment
You can do...
doTask(myParam) {
if (myParam === ContentStatusId.Review) {
// Do stuff
}
}
doTask(ContentStatusId.Review);
or
doTask(myParam) {
switch(myParam) {
case ContentStatusId.Review:
// Do stuff
break;
}
}
There is nothing calling pass by reference in javascript.
Everything gets passed by value only.
E.g
If in case of primitive value
e.g
var a = 10;
console.log(a); // 10
fun xyz(a); // passing a
function xyz(a) {
a += 10;
console.log(a); // 20
} // function will receive the value. If you modify it, It will still will not be reflected back to what you passed
console.log(a); // 10
Other way round,
When you pass object to a function, The references gets copied.
e.g
var obj = { 'a': 10 };
console.log(obj.a); // 10
function xyz(obj) {
obj.a = obj.a + 10;
console.log(obj.a); // 20
} // here the obj will be copied as reference. So when you modify it, It will get reflected back to original object.
console.log(obj.a); // 20

Passing a global variable to a function

How come the following code is giving me a 0 instead of a 1? I want my function to change a variable declared outside the function but I do not want to specify the variable in the function declaration.
that = 0;
function go(input) {
input++;
}
go(that);
console.log(that);
As answered by Oriol, it doesn't work because the variable is passed by value, so you're not changing the "that" variable. A workaround would be to pass the variable name :
that = 0;
function test(input) {
window[input]++;
}
test("that");
console.log(that); // 1
That's because you are passing the variable by value, not by reference.
In javascript, all variables are passed by value, except objects, which are passed by reference (well, in fact they are passed by value too but they are a reference, see below).
And you can't change that behaviour.
Edit: If you don't know what passing by value/reference means, you should read a tutorial. But here you have some examples:
Variable passed by value
function foo(bar){
console.log(bar); // 1
bar++;
console.log(bar); // 2
}
var mybar = 1;
console.log(mybar); // 1
foo(mybar);
console.log(mybar); // 1
Variable passed by (value but used as a) reference
function foo(bar){
console.log(bar.a); // 'b'
bar.a = 'c';
console.log(bar.a); // 'c'
}
var mybar = {a:'b'};
console.log(mybar.a); // 'b'
foo(mybar);
console.log(mybar.a); // 'c'
In your case
You can do
Make your variable a property of an object (in your case, since it's a global variable, use window) and pass the object (reference), so you can alter it
window.that = 0;
function go(obj) {
obj.that++;
}
go(window);
console.log(that); // 1
Use a return value
var that = 0;
function go(input) {
return input++;
}
that = go(that);
console.log(that); // 1
Note that you can't do
Convert your variable into an object
var that = new Number(0); // Now it's an object number
function go(input) {
input++;
}
go(that);
that *= 1; // Now it's a literal number
console.log(that); // 0
That's because objects are passed by value too, but they are a reference. That means that inside the function you can change the properties of the outer object (because it's a reference) but you can't change the entire object, because it's passed by value.
See examples here: https://stackoverflow.com/a/3638034/1529630
This has to do with pointers, scope, passing variables by reference, and all that jazz.
If you really want to do this, you can pass an object in Javascript like this:
var that = {value: 0};
function go(input) {
input.value++;
}
go(that);
console.log(that.value);
All we've done is made that an object which is by definition passed as a reference in Javascript. Then we just make sure we properly modify the object's attributes.
Your code
that = 0; //Global variable
function go(input) { //input is argument and is not passed by reference
input++; //This just increments a local copy i.e 0
}
go(that); //Passed 0
console.log(that);
Instead do this
that = 0;
function go() {
that++;
}
go(); //Not passing any variable .. function can already see the gloabl "that"
console.log(that); // This will print gloabl i.e. 1
Actually you could just add console.log(input) inside the function and it would work just fine.
Please correct me if i'm wrong. Hope i helped !!
I would be glad if somebody could explain why im wrong

Categories