This question already has answers here:
Setting a variable equal to another variable [duplicate]
(3 answers)
Closed 3 years ago.
how can I achieve below things in javascript
var parent = {
a: 5,
b: 6
}
var child = parent;
console.log(child.b); // 6
//now if I change the value of b
parent.b = 7
console.log(parent.b); //7
console.log(child.b); //7
//but I want to preserve the previous value of the object property it should not change now.it should show 6 instead of 7 in case of console.log(child.b)
https://codebunk.com/b/696347863/
When you do var child = parent both child and parent refer to the same object instance in memory. If you want to copy the property of parent to the child you need to create a new object with the same keys as the parent object.
You can use spread ... or object.assign for this
var parent = {
a: 5,
b: 6
}
var child = {...parent};
var child1 = Object.assign({}, parent);
console.log(child.b); // 6
console.log(child1.b); // 6
//now if I change the value of b
parent.b = 7
console.log(parent.b); //7
console.log(child.b); //6
console.log(child1.b); //6
For deep cloning, we need to use other alternatives because Object.assign() and ... copies property values. If the source value is a reference to an object, it only copies that reference value.
Related
This question already has answers here:
How do you create a new object of the same type as some other object
(1 answer)
How to create new instance of parent class in javascript
(1 answer)
Is there a way to instantiate a new instance of a subclass from inside a super class method?
(2 answers)
Closed last month.
Overview
I have the JavaScript classes Parent, Child1, and Child2. Both children extend Parent. I want to write a method that "semi-deep" copies (explained later) the object. Because in actuallity there could be hundreds of children, I'd write this method on the parent and all children inherit that method. But the copy always returns the type that called it.
For instance, the usage would be the following:
const parent = new Parent([1, 2, 3])
const parentCopy = parent.copy() // parentCopy has type Parent
const child1 = new Child1([1, 2, 3])
const child1Copy = child1.copy() // child1Copy has type Child1
const child2 = new Child2([1, 2, 3])
const child2Copy = child2.copy() // child2Copy has type Child2
How can I do this?
What I've tried
If this were not a class, you could use destructuring:
const copy = {...original}
This is the same affect I want. However, since this is a class, I assume I'll need to eventually create a new Thing. For instance, here's how I could create a copy of Parent.
class Parent {
// ...
copy() {
return new Parent()
}
}
However, this solution means I'd need to override it for every single child. How can I say instead to create a new WhateverThisTypeActuallyis? So if this is a Child1 calling the copy, it'll create a new Child1().
What does "semi-deep" mean?
Briefly, a shallow copy is just a reference to the actual object. For instance, the following code snippet performs a shallow copy.
let object = { a: 2, b: 3 };
let copy = object;
object.a = 5;
console.log(copy.a);
This is not what I want. I want to create a new version of the object. However, I do want to shallow copy any properties the object may have. So I don't need a structured clone which does a recursive deep copy.
Other requirements
This should be pure JavaScript. I cannot use other dependencies or npm packages.
It looks like you can use this.constructor to achieve this effect. It even preserves the children's methods.
class Parent {
constructor(value) {
this.value = value
}
copy() {
return new this.constructor([...this.value])
}
}
class Child extends Parent {
greet() {
console.log("hello world")
}
}
const child = new Child([1, 2, 3])
console.log("child value", child.value)
child.greet()
const copy = child.copy()
child.value.push(4)
console.log("child value", child.value)
console.log("copy value", copy.value)
copy.value.push(4)
console.log("copy value", copy.value)
copy.greet()
This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Array.prototype.fill() with object passes reference and not new instance
(7 answers)
Closed 9 months ago.
I tried this in the chrome dev tools console:
let a = [[null,null],[null,null]]
function na(){ return Array(2).fill(Array(2)) }
let b = na();
console.log(JSON.stringify(a))
// [[null,null],[null,null]]
console.log(JSON.stringify(b))
// [[null,null],[null,null]]
So far, so good. I was expecting both a and b with the same values and strucuture. Then I wanted to test a small function that should append an extra value in each line:
function add(x) { x.map( line => line.push(null) )}
add(a)
console.log(JSON.stringify(a))
// [[null,null,null],[null,null,null]]
add(b)
console.log(JSON.stringify(b))
// [[null,null,null,null],[null,null,null,null]]
// ?! I was not expecting this extra value here...
Well, that was unexpected.
Why is that extra null appearing in add(b) ?
function na(){
return Array(2).fill(Array(2))
}
na() fills the empty Array(2) with shallow copies of the second Array(2) object.
As a result changing values in any of the clones changes the Array's value everywhere.
a = Array(5).fill(Array(3))
a[0][0] = 1
a[0][1] = 2
a[0][2] = 3
console.log(JSON.stringify(a))
So because b has 2 elements and you are using .push() to add an element to b for each of the (same) arrays, 2 new elements are added to the array.
This question already has answers here:
Using "Object.create" instead of "new"
(15 answers)
Closed 4 years ago.
Can we simply assign a value rather than using Object.create?
Rectangle.prototype = Shape.prototype;
Rectangle.prototype =
Object.create(Shape.prototype)
what is the difference between the above two statements?
The Object.create() method creates a new object, using an existing object to provide the newly created object's proto . so, if you directly assign a value to an object there is a chance that the assigned object can also mutate here is an example.
let k = {a:12, b:34};
let j = k;
console.log(`k before mutation ${JSON.stringify(k)}`);
j.b = "Mutated";//Updating j changes k too
console.log(`k after mutation ${JSON.stringify(k)}`);
where as Object.create won't mutate
let k = {a: 123, b: 34};
let j = Object.create(k);
console.log(`k before mutation ${JSON.stringify(k)}`);
j.b = "this won't mutate k";
console.log(`k after mutation ${JSON.stringify(k)}`);
This question already has answers here:
Access parent's parent from javascript object
(12 answers)
Closed 8 years ago.
I have the following code in javascript :
var x = {
a:1,
b : {
c : 2,
d : //i want value of x.a in here
}
}
I have read that accessing parent property like this is not at all possible. Is there any workaround for this?
No, there isn't. Nested objects don't have access to their hosts as in any other language as well.
You have to set the explicitly by yourself.
No, it's not possible, but your case can be written like:
var x = new function(){
this.a = 1;
this.b = {
c: 2,
d: this.a
}
};
A javascript object doesn't have a parent because you can have sharing. For example:
var a = { x: 42 };
var b = { y: a };
var c = { z: a };
here the object a is "shared" as sub-object between b and c, so what should be the "parent" or a? You can see the sharing because after executing b.y.x = 99, also c.z.x will show be 99. A single javascript object may be reachable using different paths.
DOM objects on the other hand have a parent because the DOM is a tree structure and it makes sense to talk about "the" parent of a node.
If you add a DOM node as a child of another and the node is already part of the DOM it will be removed from where it is and it will be placed in the new position.
The parent reference does not exist in javascript. What you can do is build an helper recursive function that will parse all your object and add a reference to the parent. This will build a more complex object.
Here is a video which shows how to : http://blog.wax-o.com/2014/01/how-to-find-deep-and-get-parent-in-javascript-nested-objects-with-recursive-functions-and-the-reference-concept-level-beginner/
try this:
var x = {
a: {
c: 1
},
b: {
c: 2
}
}
x['b']['d'] = x['a'];
should work ;)
This question already has answers here:
Self-references in object literals / initializers
(30 answers)
Closed 8 years ago.
I'm having a bit of an inception issue right now. I'm trying to reference an attribute of an object while creating another attribute of the object.
For example:
var x = {
a1 : "a",
b2 : this.a1,
c : "c"
}
alert(x.a1); // Returns properly
alert(x.b2); // Returns undefined.
If I try to make b2 reference x.b2, it doesn't work either. Can anyone point me in the right direction?
All in all, I'm trying to decide the value of b2 based on the value of a1 without having to take another step out of the object.
Here's a fiddle -- http://jsfiddle.net/fpG9h/
You are most definitely in need of getters and setters. You can define them like this
var obj = {
a1: "a",
get b2() {
return this.a1;
},
set b2(value) {
this.a1 = value;
},
c: "c"
}
console.log(obj.b2); // a
obj.b2 = "bbb";
console.log(obj.b2); // bbb
console.log(obj.a1); // bbb