I would like to understand well something i observe more and more.
In some circonstances, different instances from a same model change their attributes the same way (if i have 2 UserModel A and B, if i change A, B will be affected the same way).
I observed some practical cases:
When i send an instance of a model to a view constructor, they are linked, if i change the model in my view, the outside one will be affected the same way. I guess sometime we just send a pointer and not a copy of the instance to the view.
More specific with some code;
A = new UserModel();
B = new UserModel();
var Data = A.get('info'); //where info = {some: "thing"};
Data.some = 'other';
B.set('info', Data); //A.get('info') == B.get('info')
Because i got the object info and not only the attributes separately (i tested it and there is no repercution between the values this way).
So my question is, are we always using pointers with objects in javascript ? Is it specific to backbone ? I would like to understand what is behind this behavior.
Thanks.
Objects and Arrays are passed or assigned as references in javascript, not copies. If you want a copy of an object or an array, you have to explicity make a copy.
Simpler types such as numbers, boolean are copied when assigned or passed.
Strings are a bit of special case. They are passed as references, but since strings are immutable (can't be changed), you can't really use a string reference for anything because any attempt to modify the string creates a new string.
A couple examples:
// arrays assigned by reference
var a = [1,2,3];
var b = a;
a[0] = 0;
alert(b[0]); // alerts 0 because b and a are the same array
// objects assigned by reference
var c = {greeting: "hello"};
var d = c;
c.greeting = "bye";
alert(d.greeting); // alerts "bye" because c and d are the same object
// numbers assigned as copies
var e = 3.414;
var f = e;
e = 999;
alert(f); // alerts 3.414 because f is its own copy of the original number
// make a copy of an array
var g = [1,2,3];
var h = g.slice(0); // h is now a copy
h[0] = 9;
alert(g); // shows [1,2,3]
alert(h); // shows [9,2,3]
The same is true for passing arguments to a function or returning values from a function. Unless an explicit copy is created, arrays and objects are passed or returned by reference.
A shallow copy of an array can be made with the .slice() method.
var arr1 = [1,2,3];
var arr2 = arr1.slice(0); // make independent copy of first array
A shallow copy of an object can be made by copying each property from the original object to a new object.
Deep copies involve testing the type of each item being copied and recursing on the object if it is an object or array so nested objects and arrays are copied too.
Related
I just started learning about Dart.
Before Dart, I worked with Javascript and have some experience.
Now, as I was going through the documentation from Tutorial Point. They have mentioned something like this
All variables in dart store a reference to the value rather than
containing the value. The variable called name contains a reference to
a String object with a value of “Smith”.
In Javascript, I guess arrays and objects are reference types.
Meaning, If we do something like this
[Update:] This code snippet is incorrect
let a = ["apple", "orange"]
let b = a
a = ["banana"]
console.log(b) //["banana"]
but that is probably only for objects and arrays in JS (and not for const and let)
let a = 5
let b = a
a = 7
console.log(b) //5
From the quote,
All variables in Dart store a reference to the value
[Question:] Does this mean that even things like int, string.. and every variable we create in Dart are references? and the equivalence of the above code will print 7 in Dart or I am getting something wrong (in general)?
let a = 5
let b = a
a = 7
console.log(b) //7
Everything is an Object in Dart. Some objects are mutable - that is they can be modified, and some are immutable, that is they will always be the same value.
When you assign with var b = a; both b and a will reference the same Object, but there is no further association between the names b and a. If you mutate that Object by calling methods on it or assigning to fields on it (things like List.add for example) then you will be able to observe the mutated Object through either name b or a. If you assign to a then the variable b is unaffected. This is true in javascript as well.
The reason some types, like numbers or Strings, appear special is that they cannot be mutated, so the only way to "change" a is to reassign it, which won't impact b. Other types, like collections, are mutable and so a.add("Banana") would be a mutation visible through either variable referencing that list.
For example, with assignment:
var a = ['Apple', 'Orange'];
var b = a;
a = ['Banana']; // Assignment, no impact to b
print(a); // [Banana]
print(b); // [Apple, Orange]
With mutation:
var a = ['Apple', 'Orange'];
var b = a;
a.clear(); // Mutation, the _list instance_ is changed
a.add('Banana') // Another mutation
print(a); // [Banana]
print(b); // [Banana]
What is the reference in object and how to see the reference allocated to the object in javascript.I used lodash _.clone() in an object and i made a example bellow
var Obj = {id : 0, box: 0, ei : 0};
var model = {id : 0,ob : [{c: 1, a: 0}],com: _.clone(Obj)};
var old=_.clone(model)
old.id=1;
console.log(old.id===model.id); //false correct
old.com.id=1;
console.log(old.com.id===model.com.id);//true
while updating the old.id as 1 the model id has not updated,But while updating the old.com.id as 1 now the model.com.id has also updated why?
_.clone does a shallow copy. This means that it creates a new object, then for every value in the old object, it assigns the same value to the new object. For primitives (booleans, numbers, strings), this means it's copied. This is necessary so many different references can all have a value of "1" but when one of them is updated they don't all get updated. If it's a reference (Objects and Arrays), the assigned value and the original now refer to the same thing. These rules are true any time you assign something.
For example:
var a = {value:1}
var b = {value:2}
a.b = b // this sets the property "b" in a to the reference of the 'b' object.
// so a.b and b now reference the same object
// so "a.b.value" is the *same* location in memory as "b.value"
// so if you update a.b.value or b.value you'll see it change in both references (because they are the same)
This "same spot in memory" is the key. Continuing the example:
var c = _.clone(a)
// these three lines are equivalent to the line above
var c = {}
c.value = a.value
c.b = a.b
// "c.b.value" is the "same spot in memory" as "a.b.value" and "b.value"
// So when you set it to a new value that value will change for all objects
// but "a.value" was just copied to c when it was created
// So "c.value" and "a.value" are different spots in memory
// So changing "c.value" has no effect on "a.value"
Sorry if the comments are a bit hard to read but I think it helps to see it one line at a time versus a stream of sentences.
Reaching out for an explanation of what is happening in this code snippet.
The object variable options is declared and assigned to an empty object. Then another object variable parsedData is declared and set with any number of properties, including -> options that is assigned to empty options object.
During processing, options object is updated with new key/value pairs inside of a forEach loop.
When you output parsedData.options, it IS updated and you see references to the new key/value pairs.
I assumed this was javascript variable hoisting. I googled for a few minutes, but could not confirm.
I thought it was a good question to ask on StackOverFlow. Can someone confirm or provide an explanation?
FYI - The better solution is to update parsedData.options NOT options.
Code Snippet
var options = {},
parsedData = {
options: options
};
["foo","bar"].forEach(function(name,index) {
options[name] = index
})
parsedData.options
// options are Updated - Output: Object {foo: 0, bar: 1}
In Javascript, Objects are passed by reference and primitives (String, Number ...) by value.
So when you assign a variable referencing an object to a new one, a reference to this object is passed, and when you update one, the other is updated too, which is normal because they are both pointing to the same object.
So that:
let a = 1;
let b = a;
a = 2;
console.log(b); // 1, because b got the value of a
and
let a = { z: 1 };
let b = a;
a.z = 2;
console.log(b.z) // 2, because b got a reference to the object
Why can I do this:
Array.prototype.foo = function() {
this.splice(0, this.length);
return this.concat([1,2,3]);
}
But I can't do this:
Array.prototype.foo = function() {
return this = [1,2,3];
}
Both functions destroy the value of this and change it to [1,2,3] but the second one throws the following error: Uncaught ReferenceError: Invalid left-hand side in assignment
I suspect it's because allowing assignment means I could potentially change the array to something else (like a string), but I'm hoping someone out there knows for sure and/or has a more detailed explanation.
You're confusing objects with references.
An array is an object, when you use a literal like [1,2,3] you're making a new array.
A variable name like this or a is a reference to an object. If it helps, imagine an object as a person, and the reference as their nickname. You can have more than one reference to the same object, for example:
var a = [1,2];
var b = a;
b.push(3);
alert(a.length); // Gives "3"
Imagine if you had a friend named Sarah. You also sometimes call her "Ace". If Sarah gets a haircut one day, Ace has a haircut too, because "Sarah" and "Ace" are both different names for the same person.
If you use a mutating array method like a.push or a.splice (concat however is not one!), you change the existing Array object, and a still refers to the same object. This is like getting a hair cut - you may look different, but you're still the same person.
When you assign a reference to a new value, with a = [1,2,3], you're creating a new array, and changing a to refer to it. This is like finding a new friend with different hair, and deciding to call her Ace instead.
Now this is a special name generated by Javascript. It's not a given name like Sarah, but more of a title, like "mother". Your mother can get a new haircut, but you can't get a new mother. Likewise, you can't change what this refers to from inside a function.
It's not permitted to assign a value to this within a function. Suppose that you could do this, and your code looked something like:
Array.prototype.foo = function() {
return this = [1, 2, 3];
}
var a = ["beans", "rice"];
a.foo();
// a now points to an object containing [1, 2, 3]
Now, what if you did this:
var a = ["beans", "rice"];
var b = a; // b refers to the same object as a
b.foo();
// what does b refer to now? how about a?
The act of calling a function .foo() on an object should not change the identity of the object. This would be very confusing for the caller if b suddenly started referring to a different object than a simply because some method was called.
You are not allowed to re-assign this. Because the this value associated with an execution context is immutable.
Is it possible to change the value of this? Not by assignment, you cannot assign a value to this
Your case:
Array.prototype.foo = function() {
this.splice(0, this.length);
return this.concat([1,2,3]);
}
But I can't do this:
Array.prototype.foo = function() {
return this = [1,2,3];
}
When you modify the prototype adding method foo(), the first part makes the array become empty, equals to reassign its instance.
For example to var a = []
Then in the return value:
return this.concat([1,2,3]);
Remember that concat does not destroys an array, it creates a new array and returns it
Given a = ['x'] and b = ['y'], c = a.concat(b) results in c = ['x','y'], and a and b remain the same as they were
Now since you are doing this inside the array
a=['a','b','c']
then you call a.foo();, inside a will get equal a=[], with this.splice(0, this.length); then will concatenate [ ] with [1,2,3]
So if I say just a.foo(), in fact nothing happens outside if I do not assign the result to something, just a remains empty.
If a is assigned to something
c = a.foo()
then c will be [1,2,3], and a still empty [ ]
In the second part, this = [1,2,3]
It is possible to change the value of this?, not by assignment, you cannot assign a value to this
Why can I do this:
Array.prototype.foo = function() {
this.splice(0, this.length);
return this.concat([1,2,3]);
}
But I can't do this:
Array.prototype.foo = function() {
return this = [1,2,3];
}
Both functions destroy the value of this and change it to [1,2,3] but the second one throws the following error: Uncaught ReferenceError: Invalid left-hand side in assignment
I suspect it's because allowing assignment means I could potentially change the array to something else (like a string), but I'm hoping someone out there knows for sure and/or has a more detailed explanation.
You're confusing objects with references.
An array is an object, when you use a literal like [1,2,3] you're making a new array.
A variable name like this or a is a reference to an object. If it helps, imagine an object as a person, and the reference as their nickname. You can have more than one reference to the same object, for example:
var a = [1,2];
var b = a;
b.push(3);
alert(a.length); // Gives "3"
Imagine if you had a friend named Sarah. You also sometimes call her "Ace". If Sarah gets a haircut one day, Ace has a haircut too, because "Sarah" and "Ace" are both different names for the same person.
If you use a mutating array method like a.push or a.splice (concat however is not one!), you change the existing Array object, and a still refers to the same object. This is like getting a hair cut - you may look different, but you're still the same person.
When you assign a reference to a new value, with a = [1,2,3], you're creating a new array, and changing a to refer to it. This is like finding a new friend with different hair, and deciding to call her Ace instead.
Now this is a special name generated by Javascript. It's not a given name like Sarah, but more of a title, like "mother". Your mother can get a new haircut, but you can't get a new mother. Likewise, you can't change what this refers to from inside a function.
It's not permitted to assign a value to this within a function. Suppose that you could do this, and your code looked something like:
Array.prototype.foo = function() {
return this = [1, 2, 3];
}
var a = ["beans", "rice"];
a.foo();
// a now points to an object containing [1, 2, 3]
Now, what if you did this:
var a = ["beans", "rice"];
var b = a; // b refers to the same object as a
b.foo();
// what does b refer to now? how about a?
The act of calling a function .foo() on an object should not change the identity of the object. This would be very confusing for the caller if b suddenly started referring to a different object than a simply because some method was called.
You are not allowed to re-assign this. Because the this value associated with an execution context is immutable.
Is it possible to change the value of this? Not by assignment, you cannot assign a value to this
Your case:
Array.prototype.foo = function() {
this.splice(0, this.length);
return this.concat([1,2,3]);
}
But I can't do this:
Array.prototype.foo = function() {
return this = [1,2,3];
}
When you modify the prototype adding method foo(), the first part makes the array become empty, equals to reassign its instance.
For example to var a = []
Then in the return value:
return this.concat([1,2,3]);
Remember that concat does not destroys an array, it creates a new array and returns it
Given a = ['x'] and b = ['y'], c = a.concat(b) results in c = ['x','y'], and a and b remain the same as they were
Now since you are doing this inside the array
a=['a','b','c']
then you call a.foo();, inside a will get equal a=[], with this.splice(0, this.length); then will concatenate [ ] with [1,2,3]
So if I say just a.foo(), in fact nothing happens outside if I do not assign the result to something, just a remains empty.
If a is assigned to something
c = a.foo()
then c will be [1,2,3], and a still empty [ ]
In the second part, this = [1,2,3]
It is possible to change the value of this?, not by assignment, you cannot assign a value to this