jquery variable values bleeding - javascript

i am totally missing something here. I need to define a base variable. Then reference that base varialbe in a series of second variables. Each of the second variables will be provided alternate values. However I am seeing the modified values bleed back to the base variablle
for example
<script>
var a = [{a:1}];
var b = a;
b.a = 22;
alert('a-a equals' + a.a + ' and b-a equals ' + b.a);
</script>
I want a.a to equal 1 and b.a to equal 22. however I am seeing both equal 22. Can someone explain what I am missing?

You are missing the fact that var b = a; doesn't create a new copy of a into b, it actually assigns the reference of the object stored in a into b. What this means is that any actions you take against the object stored in b is happening to the object stored in a at the same time. That is because in reality they are the EXACT SAME object!
a and b are really just telling the code where it can find the underlying object in memory, and in this case they are both pointing to the same place.

var b = a; this will just copy the reference to the actual array (The array will not be copied)
You can copy your array like this -
var a1 = [{a:1}];
var a2 = JSON.parse(JSON.stringify(a1));
a2[0].a = 22;
console.log('a-a equals' + a1[0].a + ' and b-a equals ' + a2[0].a);
Or -
var a2 = $.map(a1, function (obj) {
return $.extend({}, obj);
});
Demo --> http://jsfiddle.net/vTpSk/

Javascript will not clone a reference type when you assign a to b. There are ways to do this if you want using jquery clone or extend.
for example, you could do
var a = $.extend({}, a, b);

Objects are passed by reference. When you do var b = a, since a is an array and arrays are objects, the array is passed by reference so b references the same array as a. Instead, you need to create a copy of a and store that in b.
To copy an array, you would just use a.slice(0)
// NOTE! this example doesn't work, explained below.
var a = [{a:1}];
var b = a.slice(0);
b[0].a = 22;
alert('a-a equals' + a[0].a + ' and b-a equals ' + b[0].a);
However, since your array contains an object, the object inside the array still references the same object! Therefore, you're going to have to instead loop over the array, re-creating the array from the inside out. jQuery's $.extend method can be used here:
var a = [{a:1}];
var b = [];
for (var i = 0; i < a.length; i++) {
b.push( $.extend({},a[i]) );
}
b[0].a = 22;
alert('a-a equals ' + a[0].a + ' and b-a equals ' + b[0].a);
http://jsfiddle.net/e9Lja/
an alternative is to use jquery's $.extend combined with $.makeArray:
var a = [{a:1}];
var b = $.makeArray($.extend({},a));
b[0].a = 22;
alert('a-a equals ' + a[0].a + ' and b-a equals ' + b[0].a);
http://jsfiddle.net/e9Lja/1/
though, i prefer the for loop or $.map(see pXL's answer) because $.extend isn't meant for copying arrays.

Related

Incrementing Numbers declared by new Number() via void functions

I know typeof(my_number) is a primitive number, which makes functions receive a copy of my_number instead of my_number itself, which does't make it's value change at all. This is working as expected (I also know var is deprecated, that's probably not my issue here whatever).
What i don't know is why my_object_number isn't changed. I know i could have returned number + 1 and associated it to my_object_number, but I'm intentionally trying to code something similar to what a void(int*)function would have done in C.
var my_number = 3;
var my_object_number = new Number(3);
var my_object ={
number: 3
}
function increments_number(numero){
numero = numero + 1;
}
function increments_object(number){
number.number++;
}
increments_number(my_number);
increments_number(my_object_number);
increments_object(my_object);
console.log("primitive number = 3, which increased by a function = " + my_number);
console.log("object Number = 3 , which increased by a function = " + my_object_number)
console.log("prop number of a hardcoded object = 3, which increased by a function = " + my_object.number)
the code above prints.
primitive number = 3, which increased by a function = 3
object Number = 3 , which increased by a function = 3
prop number of a hardcoded object = 3, which increased by a function = 4
I'm not sure why my_object_number isn't incremented
I know typeof(my_number) is a primitive number, which makes functions receive a copy of my_number instead of my_number itself, which does't make it's value change at all.
There is no difference between primitives and objects in JavaScript in this respect. Actually, you can forget there’s a difference at all, for the most part – in strict mode, they’ll either behave the same in every situation or throw an error. Function calls aren’t related either. Instead, the difference is between mutating a value and reassigning something that contains a value, like a variable or a property, to contain a different value.
var a = {};
var b = a;
b = {foo: 'bar'};
console.log(a); // didn’t change, because assignment to `b` changes the variable `b`,
// not the value `{}`
var d = 5;
var e = d;
e = 6;
console.log(d); // didn’t change, because assignment to `e` changes the variable `e`,
// not the value `5`
'use strict';
var a = {};
var b = a;
b.foo = 'bar';
console.log(a); // the value {} changed; all variables stayed the same
var d = 5;
var e = d;
e.foo = 'bar'; // throws an error; a primitive is indistinguishable from…
var f = Object.freeze({});
var g = f;
g.foo = 'bar'; // … an immutable object.
++, like all math operators in JavaScript, is an operation on something that contains a value – it doesn’t mutate a value. ++x acts like x = x + 1.

Are javascript object variables just reference type?

If you have a javascript variable that is an object and you make a new variable equal the the first variable, does it create a new instance of the object, or do they both reference the same object?
They always reference the same object. We can see that by trying the following:
var x = {foo:11};
var y = x;
y.foo = 42;
console.log(x.foo);
// will print 42, not 11
Object Reference explained!
Look the image for better understanding. When you create an object, suppose s1 it is having just a reference in the memory heap and now when you create another object say s2 and say s1 = s2 that means both the objects are actually pointing to the same reference. Hence when you alter either of them, both change.
Both will refer to the same object.
If you want to create a new instance:
var Person = function() {
this.eyes = 2,
this.hands = 2
};
var bob = new Person();
var sam = new Person();
Those two are different objects.
Here is the answer: when you create an object and then assign it to another it will refer to the same object.
Here is an example:
var hacker = {
name : 'Mr',
lastname : 'Robot'
};
console.log(hacker.name + '.' + hacker.lastname);
// Output Mr.Robot
// This variable is reference to hackers object
var anotherPerson = hacker;
console.log(anotherPerson.name + '.' + anotherPerson.lastname);
// Output Mr.Robot
// These will change hacker object name and lastname
anotherPerson.name = 'Elliot';
anotherPerson.lastname = 'Alderson';
console.log(anotherPerson.name + ' ' + anotherPerson.lastname);
// Output "Elliot Alderson"
// After it if you try to log object hacker name and lastname it would be:
console.log(hacker.name + '.' + hacker.lastname);
// Output "Elliot Alderson"
You can check the link here and play with it. It is not to complicated.
JSBIN Object Hacker
If you mean something like this
var a = { foo: "foo" };
var b = a;
then yes. They reference the same object.

Number Objects Passed Into Functions by Reference

I was reading somewhere that when we pass an object into a function "...JavaScript always uses the Object by reference when it passes as argument..." What I think this implies is (correct me if I'm wrong) is that if the function was to modify the object in some way, it would change the original defined object. I tried illustrating this with some code and it does do what I think it does but when I try the example in the blog post with a Number obj, it doesn't change the original value in that object. Please see my jsbin: https://jsbin.com/wociro/edit?js,console,output
console.clear();
/**myobject Object**/
function myobject() {
this.value = 5;
}
var o = new myobject();
console.log("Original value of o: " + o.value); // o.value = 5
function objectchanger(fnc) {
fnc.value = 6;
}
objectchanger(o);
console.log("New value of o: " + o.value); // o.value is now equal to 6
/*Number Object*/
var num2 = new Number(2);
console.log("Original value of num2: " + num2);
function numberChanger(fnc) {
return fnc + 1;
}
console.log("num2 after running numberChanger: " + numberChanger(num2));
console.log("New value of num2: " + num2); //looks the same
Am I missing something?
Number objects are still objects. So their value is a reference, and if a function alters a property of an object passed as an argument, that object will be affected outside the function.
function changer(obj) {
obj.foo = 'bar';
}
var num = new Number(123);
console.log(num.foo); // undefined
changer(num);
console.log(num.foo); // 'bar'
However, the value wrapped inside the number object is not stored as a property. It's stored as a [[NumberData]] internal slot. ECMAScript provides no way to alter that slot, so you can't change the number.
Your attempt of fnc+1 unwraps the number object to get its [[NumberData]], and adds 1 to that. But the result is just discarded, it's not stored back in the [[NumberData]] slot of fnc.
If you want to be able to achieve something analogous to changing the [[NumberData]], you can
function MyNumber(num) {
this.__number__ = +num;
}
MyNumber.prototype = Object.create(Number.prototype);
Object.getOwnPropertyNames(Number.prototype).forEach(function(prop) {
var desc = Object.getOwnPropertyDescriptor(Number.prototype, prop);
if(desc && desc.value && typeof desc.value == 'function') {
var native = desc.value;
desc.value = function() {
return native.apply(this.__number__, arguments);
};
Object.defineProperty(MyNumber.prototype, prop, desc);
}
});
var num = new MyNumber(123);
console.log(+num, num+'', num.toFixed(2)); // 123, "123", "123.00"
num.__number__ = 456;
console.log(+num, num+'', num.toFixed(2)); // 456, "456", "456.00"
I actually had a lot issues when I started getting into the object side of JavaScript myself. Best way I can explain is by these examples.
Objects link.
var obj = {a: 5};
var b = obj.a;
b = 2;
// obj.a: 2
// b: 2
This will link to the object value I believe. So if you change b it will also change obj.a.
HTML DOM object link with odd behavior
var x = document.getElementById("some_div_id");
x.innerHTML = "example"; // this works
var x = document.getElementById("some_div_id").innerHTML;
x = "example"; // this doesn't, it thinks that it's document.getElementById("some_div_id");
Took me time to figure what was wrong when I first did the second DOM method.
Variables are not linked but copied.
var a = 5;
var b = a;
b = 2;
// a: 5
// b: 2
As you can see, this doesn't link the value but creates a new one based from it.
Deep copying from objects trick.
function deepCopy(objValue) {
return JSON.parse(JSON.stringify(objValue));
}
var obj = {a: 5};
var b = deepCopy(obj.a);
b = 2;
// obj.a: 5
// b: 2
This was a trick given to me some time back when I had issues wanting a object value being stored in a variable and edited but without it being linked to the object value. After a while I found I never needed it after improving my coding skills.
Also last note. I read somewhere in clean JavaScript coding that you shouldn't need to use the new object method unless it's a Date() object or or simulated class, or you may run into typeof and value check issues with ===.
Can't be certain if this is error free but hope this helps explains better.
In Javascript, objects refer to an array, indicated by [] or an object {}. You can verify the type of the variable by using typeof. These are passed by reference.
typeof [2, 5, 3] //object
typeof { a: 10} // object
If you pass the object literal to a function and modify the value of the property 'a', it would result in the value being modified.

using array.shift() affects wrong variable

I'm assuming I'm doing something really dumb here. I basically have an array that I'm passing into a function. I want to remove an element of that array and do a bunch of stuff to it, and then iterate through the rest of the array as long as there are still members in that array. When the array is empty, I want to loop back and run through the original array again.
However, I'm running into a weird issue when using array.shift(). It seems to be affecting the wrong variable if that even makes sense.
Abstract example as follows:
var originalArray = [1,2,3,4,5,6,7,8,9]
function goThroughArray(array){
var untouchedArray = array
console.log('untouched array before is ' + untouchedArray)
var insideArray = untouchedArray
console.log('inside array is ' + insideArray)
var removedNumber = insideArray.shift()
console.log('removed number: ' + removedNumber + ' from insideArray')
console.log('inside array after is ' + insideArray)
console.log('untouched array after is ' + untouchedArray)
}
goThroughArray(originalArray)
The console log output yields:
untouched array before is 1,2,3,4,5,6,7,8,9
inside array is 1,2,3,4,5,6,7,8,9
removed number: 1 from insideArray
inside array after is 2,3,4,5,6,7,8,9
untouched array after is 2,3,4,5,6,7,8,9
This is without any looping going on. Can someone explain why doing the shift() on the insideArray ALSO affects the untouchedArray??
I would expect that the insideArray would lose it's first member which is stored as "removedNumber" but why is the untouchedArray also losing it's first member?
EDIT
function addOne(number){
console.log('number in is: '+number)
var original = number;
var modified = original
console.log('original before is ' + original)
console.log('modified before is ' + modified)
modified++
console.log('original after is ' + original)
console.log('modified after is ' + modified)
}
addOne(1)
Yields:
number in is: 1
original before is 1
modified before is 1
original after is 1
modified after is 2
NEW EDIT
Although this question is super old, I figured I would update with a much cleaner method to solve this question:
JSON.parse(JSON.stringify(obj))
will create a copy of the object.
In Javascript objects are never copied. If you write
var a = [1, 2, 3, 4];
var b = a;
both a and b are just pointers to the same array object. Thus for example executing a.push(99) you will see the new element when dumping b too.
It seems that copies are done with immutable types like numbers or strings:
var a = 14;
var b = a;
b = b + 3;
console.log(a); // still 14
but this happens because the + operator returns a new number object and b is bound to this new one instead of the old one.
If you need to make a copy you must do that explicitly. For arrays the solution is calling the slice method passing no parameters.
var b = a.slice(); // Makes a new independent copy of the array
In JS, assignments are done by value:
var a = 1,
b = a; // 1 (by value)
a = 2;
b; // 1 (not modified)
However, in the case of objects, that value is a reference in memory. That means that if you modify a property of the object, you will see the change in all variables:
var obj1 = {},
obj2 = obj1;
obj1.foo = 'bar';
obj2.foo; // 'bar' (the change is reflected in the other variable)
obj1 = {}; // However, if you replace the entire object, the change
// won't be reflected because assignments are done by value
obj1.foo; // undefined
obj2.foo; // 'bar'
javascript is pass by value language. read this link for more inforamtion or google it.
In this case, you should clone your array.
try this
let insideArray = untouchedArray.slice();

Is it possible to create a variable based on the value of more than one variable?

For example A = 10, i want to create a variable with the value in it.
Like this: var i10 or if A = 2, i wanna create a variable like this var i2.
For e.g. A = 10 and B = 5, i want a var A10B5, is that possible?
Edit: more information
It is possible, as explained in detail in this question on SO.
A = 10;
B = 5;
window['A' + A + 'B' + B] = 'Hello';
alert(A10B5);
// alerts: Hello
See a demo in this jsfiddle.
I don't see the point of it though though, since you have to keep a reference of the name of this object it's easier to store the value in a local variable inside a function or object that has always the same name or use an array to store the value.
Proposed solution for the intended use:
Use a two-dimensional array:
Calendar[A][B] = 'value';
By creating dynamic variables you will have to rebuild the name of the variable every time you need to access it it. By using a two-dimensional array you can just use the array with both variables, that spares you the code to rebuild the variable name over and over again and makes it easier to read and maintain.
var A = 10, B = 5;
window['A' + A + 'B' + B] = "You should avoid polluting global " +
"scope at all costs.";
alert(A10B5);
Instead you should resort to objects:
var myVars = {}, A = 10, B = 5;
myVars['A' + A + 'B' + B] = "Just like this.";
alert(myVars.A10B5);
You can create dynamic variables with eval() function
var a = 10;
eval("variable" + a + " = a");
this return a variable with name "variable10" and value "10".
Take a look here too!
For more information: w3schools eval()
Hope it helps ^_^
You can have A = 10 and B = A which takes the same amount in a different variable, however, you also can make an if statement like
if(A > 10){ A = 11 }
check this out
`a = 'varname';
str = a+' = '+'123';
eval(str);
alert(varname);
`

Categories