a = [1,2,3];
b = [[1,2,3],[4,5,6]];
Why is that in javascript a== b[0] return false?
Thank you
In javascript objects are compared by references.
That said: a references to objects are compared, not the objects' contents.
Thus, One object {} will never be equal to another {} even though their contents are equal.
var a = {},
b = {}; // not equal
Whereas if you create a variable by assigning another reference to it like:
var a = {},
b = a; // equal
then both variables would hold the same reference and would be equal.
Related
How can I compare two the same types against each other in JavaScript?
So a == b should return true, because they are both arrays.
So it doens't matter what the contents of the variable are. The comparison should be something like this;
var a = [];
var b = [];
var c = "this is a string";
var d = "this is also a string";
if(a type == b type) // true because both arrays
if(c type == d type) // true because both strings
if(a type == d type) // false because not the same type (string) or (array)
To compare two types in javascript, use typeof.
(function () {
var a = [];
var b = [];
var c = a;
var d = "a";
var e = "a";
console.log(typeof(a) == typeof(b));
console.log(typeof(a) == typeof(c));
console.log(typeof(d) == typeof(e));
})();
a and b are not exactly the same. If the type is a reference type, comparing them just checks their references. In this case a and b are arrays, but they have separate objects in the memory and separate references to them.
When you assign a to c, it just copies the reference from a and assigns it to c. And now c also refers to the same object as a. So while comparing a and c returns true, because they have the same reference value(address of the memory).
Something like this. (number in the [] is the address of the memory, number in the () is the value)
a(0x1616) ---------> [0x1616] <--|
b(0x1717) ---------> [0x1717] |
c = a; |
c(0x1616) -----------------------|
[] is Javascript Array type Object.
== does type check first.
when you are doing a == b although they are both array but they are different array object like they have different values and references.So it becomes false
when you are assigning c = a. It's called passing reference of a array to c.
therefore they are pointing to same array object. so a == c becomes true.
If both operands are objects, then JavaScript compares internal references which are not equal when operands refer to different objects in memory.
The variables a and b refer to two objects with identical properties, but they are each distinct instances. On the other hand a and c both refer to the same instance.
The reason for this is that internally JavaScript actually has two different approaches for testing equality. Primitives like strings and numbers are compared by their value, while objects like arrays, dates, and plain objects are compared by their reference. That comparison by reference basically checks to see if the objects given refer to the same location in memory.
Please see below snippet for comparison of objects in Javascript.
(function () {
var a = [];
var b = [];
var c = a;
var d = "a";
var e = "a";
console.log(a == b);
console.log(a == c);
console.log(d == e);
})();
As I understand objects are passed by reference in JavaScript (and primitives are passed by value?).
var a, b;
a = {
Foo: "Bar"
}
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
This worked similarly with arrays but did not work like I expect with functions:
var a, b;
a = function(){ return 20; }
b = a;
a = function(){ return 40; }
console.log(b()); // returns 20 ?
I'm confused because I thought functions are objects. Shouldn't the above example return 40?
In the first case, a.Foo = ..., You are changing the value of a property in the object, referred by both a and b. This is called mutating an object.
But in the second case, you are making a refer a new function object. Now, a and b are referring to different function objects.
That is why you are getting 20 in the second case.
First regarding the question in the title (which is actually different from what you demonstrate with the code examples):
"As I understand objects are passed by reference in JavaScript"
No, Javascript doesn't support passing parameter by reference at all. All parameters are passed by value, but the value can be a reference.
Example:
var a = { answer: 42 };
function f(x) {
alert(x.answer); // shows 42
x = { answer: 0 };
alert(x.answer); // shows 0
}
f(a);
alert(a.answer); // shows 42
As the parameter is passed by value, the variable x is separate from the variable a, so assigning a new object to x doesn't change the value of a.
Back to your code:
When you assign an object reference from a variable to another, it's the reference that is copied, not the object. You get two variables that reference the same object.
Either of the variables can be used to access members in the object, which your first code example demonstrates.
If you assign a new object to the first variable, you will replace the reference in the variable, you will not overwrite the object that it currently points to. The object is still intact, and the second variable still points to it. You get two variables that point to one object each, which your second code example demonstrates.
Further to #thefoutheye's answer, consider the following proof of your statement functions are objects:
var a, b;
a = function() { return 20; }
a.Foo = "Bar";
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
You are reassigning the variable a to a new function. That's not the same as changing a property value.
Try:
var a, b;
a = {Foo: function() {return 20;}};
b = a;
a.Foo = function() {return 40;};
console.log(b()); // returns 40
I have an object that looks like this:
var MyObject = {
prop1 = 12345,
prop2 = "string1",
ListOfOtherObject = an array of another type of object,
ListOfAnotherObject = an array of objects}
Let's say I have two objects: Object1 and Object2. Object2 was initially a deep-copy of Object1 and it was modified through the user's interactions with the UI. I'm looking to get the difference between both objects, especially when it comes to the arrays.
For instance, ListOfOtherObject in Object2 might contain a modified version of some objects as well as new objects.
I'm thinking about looping through each array and then looping through each object within but there might be some more efficient way to do it, especially with jquery. Or may be going with JSON.stringify and compares strings and retuns some sort of string difference. I was wondering if anyone had any suggestions on how to do this.
Thanks.
You need to specify what your comparison needs to do. For example, given:
var o = {name: 'fred'};
var p = {name: 'fred'};
var a = {o:o};
var b = {o:o};
then:
a == b; // false, a and b are different objects
a.o == b.o; // true since a.o and b.o reference the same object
but if comparing objects:
b.o = p;
a.o == b.o; // false since a.o and b.o reference different objects
or if comparing primitives:
a.o.name == b.o.name; // true since the value of both expressions is the string 'fred'
// even though a.o and b.o are different objects
Does Type or constructor matter? What about:
b.o = [];
b.o.name = 'fred';
a.o.name == b.o.name; // true or false? a.o is an object, b.o is an array
I feel puzzled when I rethink of these two functions:
The first one goes like this:
var test = [1,2,3];
var ele = test[0];
ele= 2;
alert(test[0]);
The result is 1. I think this is obvious. But when I meet this:
var test = [{id:1},{},{}];
var ele = test[0];
ele.id = 2;
alert(test[0].id);
The result turns to be 2
So could anyone tell me that how the javascript work when it happens like this in the object array?
In JavaScript, objects are assigned by reference, rather than copied in memory. So if you assign an existing object to a different variable, both will point to the same object in memory. Modifications to either will therefore be reflected in both.
var a = {id: 1, name: "bob"};
var b = a;
console.log(b.name); // bob
b.name = "bill";
console.log(a.name); // bill
So in your example, executing ele.id = 2; operates on the memory location holding the object at test[0]. The change to the id property of that object is reflected in both variables referencing it (test[0], ele)
Note that if you had assigned the entire array test to ele, modifying one of the array members would have been reflected in both test, ele since Arrays are objects in Javascript:
var test = [1,2,3];
// Assign array test to ele
var ele = test;
// Modify one member
ele[0] = 2;
alert(test[0]); // 2
Is it possible for one variable to point to another in an array like this,
var theArray = [0,1,2,3];
var secondElement = //somehow point to theArray[1]
so that if I modify theArray[1], secondElement should also be modified and vice versa (possibly, without using functions)?
There's no way to do that directly. The array could be an array of objects, and you could modify properties of the objects instead of the array entries directly. Then you would have:
var theArray = [ { value: 0 }, { value: 1 }, { value: 2 }, { value: 3 } ];
var secondElement = theArray[1];
then changes to theArray[1].value would also be visible in secondElement.value.
I would offer the observation that functions are friendly things and they won't hurt you if you don't try and pick them up by the tail.
You can use object properties and wrap your array with an object:
var a = {arr: [1,2,3,4]};
var b = a;
b.arr[0] = 777;
console.log(a.arr);
This method has the advantage that you can also assign new values to both a.arr and b.arr.
var a = {arr: [1,2,3,4]};
var b = a;
a.arr = [777,888];
console.log(b.arr);
You're asking about references -- for primitive values, it's not directly possible in Javascript. It is possible w/r/t objects:
C:\WINDOWS>jsdb
js>a = []
js>b = {refToA: a}
[object Object]
js>b.refToA.push(3)
1
js>a
3
js>a.push(4)
2
js>b.refToA
3,4
js>
In the above example, the object b has a property refToA which contains the object a; both reference the same actual object, so changes to the object b.refToA and a are reflected through both ways of accessing it. This reference is broken if you reassign either b.refToA or a. Similarly with arrays:
js>x = {y: 3, toString: function() { return 'y='+this.y; }}
y=3
js>a = [x]
y=3
js>b = [3,x]
3,y=3
js>a[0].y = 22
22
js>b
3,y=22
js>b[1].y = 45
45
js>a
y=45
a[0] and b[1] both have a value that is the same reference to an object.
The effect you're looking for can only be achieved if the shared object is a mutable container, so that your two desired variables have (and always have) the same value, which is a reference to the shared mutable container. You can change values in the container, and they will be seen by both means of access. Primitive values (e.g. numbers and strings) are not mutable containers so they can't be used this way.