This question already has answers here:
How do I correctly clone a JavaScript object?
(81 answers)
Closed 7 years ago.
I have query object
var q = {
age: 10,
'profile.contry': 'india'
};
Now I duplicate the q variable and remove key from a duplicate variable.
var duplicateQ = q;
delete duplicateQ['profile.contry']; // I have removed 'profile.country' from duplicateQ.
console.log(q); //Object { age: 10 }
console.log(duplicateQ); //Object { age: 10 }
Why are both the variables affected? How can I remove the property from only one of them?
It's because q and duplicateQ refer to the same object. Thus, when you delete a property on one object, it effects both (since they both point to the same object).
You need to copy/clone the object.
In ES6, you can use the .assign() method:
var q = {age:10, 'profile.contry': 'india'};
var duplicateQ = Object.assign({}, q);
delete duplicateQ['profile.contry'];
Output:
console.log(q);
// {age: 10, profile.contry: "india"}
console.log(duplicateQ);
// Object {age: 10}
You aren't duplicating q, instead, you're copying a reference to different variable.
Both q and duplicateQ point to the same object, the same location in your computer's memory.
In order to make this work, you're going to have to clone the object, then you can delete (/ modify) individual properties on the separate variables.
A quick-and-dirty example:
var a = { a: 1, b: 2 },
b = JSON.parse(JSON.stringify(a));
delete b.a;
document.body.textContent = JSON.stringify(a) + ' ' + JSON.stringify(b);
Related
This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 29 days ago.
In JS/typescript, lets say I have an object like this
var obj = {
a: {
b:{
c:1
}
}
}
And I have a string "b.c". How can I evaluate this using only those variables and get the value 1 from the object without using hacks like eval since typescript would complain.
Thanks
It I understood you question, the keys are known, if so you can use the '[]' to access it :
const a = b.c
is the same thing as
const a = b['c']
but in the second case you can of course use a variable.
Applying this to your object, it would look something like this :
const obj = {
a: {
b: {
c: 1
}
}
}
const outerKey = 'a'
const middleKey = 'b'
const innerKey = 'c'
const value = obj[outerKey][middleKey][innerKey]
console.log(value)
Hope it helped you !
This question already has answers here:
Modifying a copy of a JavaScript object is causing the original object to change
(13 answers)
Closed 6 months ago.
var arr = []
var obj = {
a: undefined,
b: undefined,
c: undefined
}
var a = 0
while (a !== 100) {
arr.push(obj)
a++
}
var randNum
for (var i = 0; i < arr.length; i++) {
randNum = Math.floor(Math.random() * 2)
console.log(Math.floor(Math.random() * 2))
arr[i].a = Math.floor(Math.random() * 2)
arr[i].b = 5
}
console.log(arr)
When I console log arr, arr[n].a always equals one number, but thats not what I want, I want it to output a random number, like 0 or 1.
The issue is as VLAZ mentioned in their comment. To fully explore this, we need to understand reference vs. value types in JS.
Let's look at a simple program:
let a = 1;
let b = a;
a = 2;
console.log(b) // prints 1
This works because we're storing a simple, primitive type like a number. With more complex types like arrays and objects, we'll see different behavior.
let a = { foo: true, bar: true };
let b = a;
a.foo = false;
console.log(b) // prints { foo: false, bar: true }
This is because more complex types in JS like arrays and objects are passed by reference, not by value. In essence, this means that when we store an object using a variable, the variable is not storing the values, but rather a reference to the object's location in your machine's memory. Let's add comments to the above code for clarity.
// a stores a pointer to memory location A, where our object literal lives
let a = { foo: true, bar: true };
// b stores a pointer to memory location A
let b = a;
// change a value on the object in memory location A
a.foo = false;
// print the value in memory location A
console.log(b)
This reference vs value differentiation has to do with the complexities of managing memory when we have potentially large, dynamic objects, so JS does a bunch of low-level stuff for us behind the scenes and gives us a nice user-friendly syntax for instantiating a data type that would be more complicated to implement manually in a lower-level language. However, we still have to be aware of this difference.
The crux of your issue is that in each index of your array, you're storing a reference to the exact same object, so when you update one index, you're actually updating the value at the memory location the index is pointing to. Since all the indices are pointing to the same memory location, changing one behaves similarly to changing them all.
Fortunately, armed with this information we can simply devise a way to create a new object on each iteration, whether by copying the reference object or just passing an object literal to the Array.push() method. Here's a potential solution.
let arr = [];
for (let i = 0; i < 100; i++) {
// this "object literal" is defined when push is called, creating a new object on each iteration
arr.push({
a: Math.floor(Math.random() * 2),
b: 5,
c: undefined
});
}
This question already has answers here:
How do I reference the same Object's properties during its creation? [duplicate]
(5 answers)
Closed 9 years ago.
Can one reference own properties on initialization of object?
I have an object that should be unique and only exist as one so I
have no initializer etc.
Using something like this:
var Myobj = {
property1 : aaa,
property2 : bbb,
property3 : {a: self.property1 }
/* ^-- is this somehow possible without using a function?
Or a better way to solve / structure this. .init()
best option? */
};
>> Fiddle <<
The real object, (in the real code), has an add function that takes options on
what function to use etc. It is sort of a wrapper for "addEventListener" where
the point is to be able to remove listener - which require non anonymous function
reference.
Function to use within Myobj is specified by string, or numeric key in options to
Myobj.add().
Object literals remain undefined until the closing }, so you'd either have to make property3 a function or make the whole object a function.
var Myobj = {
property1 : 'aaa',
property3 : function (){ return { a : this.property1 } }
};
or
var MyObj = function(){
this.property1 = 'aaa',
this.property3 = { a: this.property1 }
}
var MyObjInstance = new MyObj();
This has been asked a lot of times: Access properties while declaring object?
It works if you use a placeholder array:
var prop = new Array();
var Myobj = {
property1 : 'aaa',
property2 : 'bbb',
property3 : {a: prop}
};
prop.push(Myobj.property1);
window.alert(Myobj.property3.a);
http://jsfiddle.net/y2XwC/1/
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Self-references in object literal declarations
var obj = {
value: 10,
value2: value + 2
};
How can I do the above? (Assuming it's even possible)
I am using a lot of jQuery's $.extend to add more properties that rely on the previous values being added; so that modifying a few values automatically correct the rest.
You can't do it in declaration, but you could always make a function. The following will always return a value 2 greater than that stored in value:
var obj = {
value: 10,
getValue2: function(){ return this.value + 2; }
};
If you don't want the value of value2 to change along with value, you could declare a placeholder variable and declare the object using that:
var placeholder = 10;
var obj = {
value: placeholder,
value2: placeholder + 2
};
I am not 100% sure if you can do this at the time of declaration. You could, however, do it afterwards:
using extend:
var obj = {
value: 10
};
$.extend(obj, {
value2: obj.value + 2
});
http://jsfiddle.net/KgKgf/
just javascript:
var obj = {
value: 10
};
obj.value2 = obj.value + 2;
http://jsfiddle.net/KgKgf/1/
Does Javascript have associative arrays? Please explain.
Nope; JavaScript arrays are just numeric keys and mixed values. The same thing can be achieved (or, actually, it's exactly the same as associative arrays in other languages) with objects:
var foo = {
a: 123,
b: 'CDE'
};
foo.a; // 123
foo['a']; // 123
You could use arrays:
var foo = [];
foo.a = 123;
foo.b = 'CDE';
foo.b; // CDE
foo['b']; // CDE
HOWEVER, this should never be done because this will not enter the key/value pairs into the array, but add them to the array object as properties. (besides, {a: 123} is easier than a = []; a.a = 123) If you need key/value pairs, use Objects. If you need an enumerated list, use arrays.
This answer is pretty much a copy-paste of my previous answer on this question.
The situation has changed in the five years since this question was asked.
Due to weak typing associative arrays can be faked in JavaScript:
>> var names = new Array();
undefined
>> names["first"] = "Dotan";
"Dotan"
>> names["last"] = "Cohen";
"Cohen"
>> for ( key in names ) { console.log(key+" "+names[key]) }
undefined
first Dotan
last Cohen
That is sometimes useful, and all browsers released since 2012 support it, but there are caveats! The array cannot be simply read back:
>> names
Array [ ]
More importantly, the array's length cannot be easily retrieved:
>> names.length
0
Therefore this is not an associative array in the sense that JavaScript would have supported it had it been intended, but rather a workaround that is often useful if for whatever reason a real JS object does not support what you need:
>> var names = {};
undefined
>> names.first = "Dotan";
"Dotan"
>> names.last = "Cohen";
"Cohen"
>> for ( key in names ) { console.log(key+" "+names[key]) }
undefined
first Dotan
last Cohen
>> names
Object { first: "Dotan", last: "Cohen" }
>> Object.keys(names).length
2
The closest we have is an object; the easiest way you can define this is using object literal syntax.
var assocArray = {
key: 1,
key2: 2
};
You should be wary of a few things however:
It does not have a .length property.
You should use for in to iterative over it, rather than for(;;;);, but should combine it with hasOwnProperty():
for (var x in assocArray) {
if (assocArray.hasOwnProperty(x)) {
// x = the key, assocArray[x] = the value
}
}
There is no concept of ordering/ sorting the members. Whilst all implementations I know of iterate the members in the order they were added, this is not standardised.
Instead of associative arrays. Javascript has objects. Properties of an object are addressed using a string.
var obj1 = {}; // declare empty object
var obj2 = {a: 1, b: 'string', c: [4,5]}; // obj with 3 properties, a, b, and c
// note that the 'c' property contains an anonymous array
alert(obj2.a); // shows 1
obj2.a = 'another string'; // redefine the 'a' property
obj2.cookie = 'oatmeal'; // add a new property to the object
obj2['ice_cream'] = {vendor: 'Beyers',
flavor: 'Chocolate Surprise'}; // add anonymous object as
// a new property for the object
assert(obj2.a === obj2['a']); // two ways to retrieve the value
var i = 'a'; // using an index varable
assert(obj2.a === obj2[i]); // note the i does not have apostrophes around it
See the Quirksmode docs
Something comparable in JavaScript is an object.
var my_obj = { key : 'value' }
Sure it does (kind of, use objects)
var foo = {
bar: "hello"
}
accessible with
foo.bar