I’m a bit confused here. Hopefully someone can explain.
On task 6 in this project…while working on it, I thought to just console.log this.dna first(before I actually start working on the task) inside the willLikelySurvive(). What I noticed, is that when I console.log this.dna(by calling willLikelySurvive()), it logs the mutated version and not the original dna(before it was mutated). Can’t understand why?
Here is my code so far…
(Feel free to correct other mistakes I’ve made in this projects so far, or if I’ve misunderstood something they are asking us to do)
// Returns a random DNA base
const returnRandBase = () => {
const dnaBases = ['A', 'T', 'C', 'G']
return dnaBases[Math.floor(Math.random() * 4)]
}
// Returns a random single strand of DNA containing 15 bases
const mockUpStrand = () => {
const newStrand = []
for (let i = 0; i < 15; i++) {
newStrand.push(returnRandBase())
}
return newStrand
}
const pAequorFactory = (number, strand) => {
return {
specimenNum: number,
dna: strand,
mutate () {
let mutatedDna = this.dna;
let ranDnaBase = mutatedDna[Math.floor(Math.random() * 15)];
let ranDnaBaseIndex = mutatedDna.indexOf(ranDnaBase);
console.log('Mutate this DNA strand: ' + mutatedDna);
console.log('Mutate at Base: ' + ranDnaBase + ' (with Index: ' + ranDnaBaseIndex + ')');
console.log();
if (ranDnaBase === 'A') {
const dnaB1 = ['T', 'C', 'G'];
mutatedDna[ranDnaBaseIndex] = dnaB1[Math.floor(Math.random() * 3)];
return mutatedDna;
} else if (ranDnaBase === 'T') {
const dnaB2 = ['A', 'C', 'G'];
mutatedDna[ranDnaBaseIndex] = dnaB2[Math.floor(Math.random() * 3)];
return mutatedDna;
} else if (ranDnaBase === 'C') {
const dnaB3 = ['A', 'T', 'G'];
mutatedDna[ranDnaBaseIndex] = dnaB3[Math.floor(Math.random() * 3)];
return mutatedDna;
} else if (ranDnaBase === 'G') {
const dnaB4 = ['A', 'T', 'C'];
mutatedDna[ranDnaBaseIndex] = dnaB4[Math.floor(Math.random() * 3)];
return mutatedDna;
}
},
compareDNA (pAequor) {
const dnaSequenceA = this.mutate();
const dnaSequenceB = pAequor.mutate();
console.log(dnaSequenceA);
console.log(dnaSequenceB);
let sameBaseAmount = 0;
for (let i = 0; i < dnaSequenceA.length; i++) {
if (dnaSequenceA[i] === dnaSequenceB[i]) {
sameBaseAmount++;
}
}
let sameBasePercentage = Math.floor((sameBaseAmount / dnaSequenceA.length) * 100);
//console.log(sameBaseAmount);
//console.log(sameBasePercentage);
console.log(`Specimen #${this.specimenNum} and specimen #${pAequor.specimenNum} have ${sameBasePercentage}% DNA in common.`)
},
willLikelySurvive () {
console.log(this.dna);
}
};
};
const pA1 = pAequorFactory(1, mockUpStrand());
const pA2 = pAequorFactory(2, mockUpStrand());
pA1.compareDNA(pA2);
pA1.willLikelySurvive();
compareDNA
calls the mutate
function. And you’re calling the compareDNA
function before you call willLikelySurvive
. So the dna is already mutated.
This does not create a copy of this.dna
. It just creates a new reference to the same array. So whatever you do with mutatedDna
happens to this.dna
, too.
You could create a copy by changing this line to:
let mutatedDna = [...this.dna];
2 Likes
Oh really!? I was not aware of that.
I thought we were making a copy…just like when we copy a varibale with a number, or a variable with a string, and assign them to new variables…where we can change the copies, without making changes to the values of the original variables.
let num = 1;
let newNum = num;
console.log(newNum); //Prints 1
newNum = 2;
console.log(newNum); //Prints 2
console.log(num); //Prints 1
let str = 'hello';
let newStr = str;
console.log(newStr); //Prints hello
newStr = 'bye';
console.log(newStr); //Prints bye
console.log(str); //Prints hello
const arr = [1, 2, 3];
const newArr = [...arr];
console.log(newArr); //Prints [1, 2, 3]
newArr.push(2);
console.log(newArr); //Prints [1, 2, 3, 2]
console.log(arr); //Prints [1, 2, 3]
//The above creates copies, but this creates a reference like you say:
const arr = [1, 2, 3];
const arrReference = arr;
arrReference.push(2);
console.log(arrReference); //Prints [1,2,3,2]
console.log(arr); //Prints [1,2,3,2]
But does that apply to arrays only?
Because from what I see, it does not apply to variables with numbers or strings. So lets say If I wanted to copy this.specimenNum…I can just write let newVariable = this.specimenNum;. Then make changes to newVaribale without making changes to the original this.specimenNum.
So does this technique only apply to when I want to make copies of an arry?
To arrays and objects:
const originalObj = {
num: 1
}
const newObj = originalObj
newObj.num = 2
console.log(originalObj.num) // 2
As a rule of thumb you can say that it applies to everything you can declare as a constant (const) and change nevertheless:
const num = 1
num = 2 // type error --> immutable
const obj = {
num: 1
}
obj.num = 2 // no type error --> mutable
1 Like
Ok, so arrays and objects…I’ll remeber that in the future 
And the part that we can mutate arrays and objects while declared with const is fine, I remember that Codecademy showed us that. But not what you just taught me regarding making a copy of an array. Can’t remember Codecademy teaching us that.
But how will we go about making a copy of an object and not just a reference to an object?
So lets say that this.dna was actually an object and not an array. To make a copy(and not reference), what should we write as a value of let mutatedDna = ?;, is it let mutatedDna = {…this.dna}; maybe? So instead of square barckets, we use curly braces(since it’s an object)…or?
Yes.
const obj = {
num: 1
}
const copiedObj = {...obj}
copiedObj.num = 2
console.log(obj.num, copiedObj.num) // 1, 2
const mutatedObj = obj
mutatedObj.num = 2
console.log(obj.num, copiedObj.num) // 2, 2
Try it yourself in a sandbox.
1 Like
I was just doing that 
//Making a reference:
const obj = {
num: 1
};
const newObj = obj;
console.log(newObj);
newObj.num = 2;
console.log(newObj);
console.log(obj);
//Making a copy:
const obj2 = {
num: 1
};
const newObj2 = {...obj2};
console.log(newObj2);
newObj2.num = 2;
console.log(newObj2);
console.log(obj2);
Thank you for your help!
1 Like