Koans는 불교에서 유래된 단어로, 결론을 내리기 전에 이게 왜 맞는지 깊게 고민한다는 의미를 가지고 있다고 한다. 답이 미리 제시되어 있기 때문에 고민 없이 풀면, 큰 어려움 없이 전부 다 풀 수 있지만 그게 왜 정답인지 깊게 고민해 보는 시간을 갖지 않는다면 충분히 성장하기 어려울 것이다. 즉, '왜?' 라는 물음에 대해 꼭 깊은 고찰을 하고 넘어가자는 의미이다.
describe('Array에 대해서 학습합니다.', function () {
it('Array의 기본을 확인합니다.', function () {
const emptyArr = [];
expect(typeof emptyArr === 'array').to.equal(false); // 배열은 다 'object'로 나온다.
expect(emptyArr.length).to.equal(0);
const multiTypeArr = [
0,
1,
'two',
function () {
return 3;
},
{ value1: 4, value2: 5 },
[6, 7],
];
expect(multiTypeArr.length).to.equal(6);
expect(multiTypeArr[0]).to.equal(0);
expect(multiTypeArr[2]).to.equal('two');
expect(multiTypeArr[3]()).to.equal(3); // 배열 속 함수 **
expect(multiTypeArr[4].value1).to.equal(4);
expect(multiTypeArr[4]['value2']).to.equal(5);
expect(multiTypeArr[5][1]).to.equal(7);
});
it('Array의 요소(element)를 다루는 방법을 확인합니다.', function () {
const arr = [];
expect(arr).to.deep.equal([]);
to.equal이 아닌 to.deep.equal 을 쓴 이유
to.deep.equal() 배열의 요소나 객체의 속성이 서로 같은지 확인하는 matcher 이다.
예를 들어 [] === [] // false 이기 때문에 기존처럼 to.equal()을 쓰면 false 가 뜬다.
다시 말해 to.deep.equal은 배열과 객체 속의 내용 그 자체를 비교하는 것!
to.eql() 로도 쓸 수 있다.
arr[0] = 1;
expect(arr).to.deep.equal([1]);
arr[1] = 2;
expect(arr).to.deep.equal([1, 2]);
arr.push(3);
expect(arr).to.deep.equal([1, 2, 3]);
const poppedValue = arr.pop();
expect(poppedValue).to.equal(3); // arr.pop() 은 삭제하는 요소 그 자체 값을 나타낸다.
expect(arr).to.deep.equal([1, 2]);
});
it('Array 메소드 slice를 확인합니다.', function () {
const arr = ['peanut', 'butter', 'and', 'jelly'];
expect(arr.slice(1)).to.deep.equal(['butter', 'and', 'jelly']);
expect(arr.slice(0, 1)).to.deep.equal(['peanut']);
expect(arr.slice(0, 2)).to.deep.equal(['peanut', 'butter']);
expect(arr.slice(2, 2)).to.deep.equal([]); //2번째 요소부터 1번째 요소까지 자르니 내용물은 없게된다.
expect(arr.slice(2, 20)).to.deep.equal(['and', 'jelly']);
expect(arr.slice(3, 0)).to.deep.equal([]);
expect(arr.slice(3, 100)).to.deep.equal(['jelly']);
expect(arr.slice(5, 1)).to.deep.equal([]);
// arr.slice는 arr의 값을 복사하여 새로운 배열을 리턴한다.
// 아래의 코드는 arr 전체를 복사한다. 자주 사용되니 꼭 기억하기! arr.slice() 도 가능하다.
expect(arr.slice(0)).to.deep.equal(['peanut', 'butter', 'and', 'jelly']);
});
it('Array 메소드 shift와 unshift를 확인합니다.', function () {
const arr = [1, 2];
arr.unshift(3); //맨앞에 3을 넣고 길이(3)를 반환한다.
expect(arr).to.deep.equal([3, 1, 2]);
const shiftedValue = arr.shift(); //맨앞에 요소를 제거하고 해당 요소를 반환한다.
expect(shiftedValue).to.deep.equal(3);
expect(arr).to.deep.equal([1, 2]);
});
});
unshift() 와 shift()의 차이
- unshift는 맨 앞에 () 안 요소를 집어넣고, 해당 배열의 총 길이를 반환한다.
- shift는 맨 앞에 요소를 삭제하고, 삭제한 요소의 값을 반환한다.
it('Array를 함수의 전달인자로 전달할 경우, reference가 전달됩니다.', function () {
// call(pass) by value와 call(pass) by reference의 차이에 대해서 학습합니다. ***
const arr = ['zero', 'one', 'two', 'three', 'four', 'five'];
function passedByReference(refArr) {
refArr[1] = 'changed in function';
}
passedByReference(arr);
expect(arr[1]).to.equal('changed in function');
const assignedArr = arr;
assignedArr[5] = 'changed in assignedArr';
expect(arr[5]).to.equal('changed in assignedArr');
const copiedArr = arr.slice();
copiedArr[3] = 'changed in copiedArr';
expect(arr[3]).to.equal('three');
});
call by value & call by reference
한글로 된 자료를 찾다가 원문을 찾아오게 되었다. 번역할 시간과 에너지는.. 없으므로 알아서 이해하자!
기억할 것
- Call by Value에서 a의 값을 b에 할당할 때 a와 b는 같은 값을 갖지만, 다른 메모리 공간에 저장된 별개의 값이다.
- Call by Reference에서 a의 값을 b에 할당할 때 a === b 이다. (즉, 같은 주소값을 참조)
아래 원문 참고
Call by Value: Suppose there is a variable named “a”. Now, we store a primitive value(boolean, integer, float, etc) in the variable “a”. Let us store an integer value in “a”, Let a=5. Now the variable “a” stores 5 and has an address location where that primitive value sits in memory. Now, suppose we copy the value of “a” in “b” by assignment (a=b). Now, “b” points to a new location in memory, containing the same data as variable “a”.
Thus, a=b=5 but both point to separate locations in memory.
This approach is called call by value where 2 variables become the same by copying the value but in 2 separate spots in the memory.
Features of call by value:
- Function arguments are always passed by value.
- It copies the value of a variable passed in a function to a local variable.
- Both these variables occupy separate locations in memory. Thus, if changes are made in a particular variable it does not affect the other one.
Example: This example shows the usw of the above-explained approach.
// By value (primitives)
var a = 5;
var b;
b = a;
a = 3;
console.log(a);
console.log(b);
|
Output: “b” was just a copy of “a”. It has its own space in memory. When we change “a” it does not have any impact on the value of “b”.
Call by reference: Let’s say, we have an object stored in the variable “a”. The variable stores the location or the address where the object lives. Now we set b=a. Now that new variable “b” instead of pointing to a new location in the memory, points to the same location where “a” does. No new object is created, and no copy is created. Both variables point to the same object. This is like having 2 names.
This is called by reference. It behaves quite differently from by value. All objects interact by reference.
Features of By reference:
- In JavaScript, all objects interact by reference.
- If an object is stored in a variable and that variable is made equal to another variable then both of them occupy the same location in memory.
- Changes in one object variable affect the other object variable.
Example: Over here, when we set d=c, “d” points to the same location in memory where “c” does. At first, we have a name-value pair stored in “c”. Now when we change a property using “c”, it changes the property in “d” also because both point to the same object. Changes in one it affects.
// By reference (all objects (including functions))
var c = { greeting : 'Welcome' };
var d;
d = c;
// Mutating the value of c
c.greeting = 'Welcome to geeksforgeeks';
console.log(c);
console.log(d);
|
Output:
{greeting: 'Welcome to geeksforgeeks'}
{greeting: 'Welcome to geeksforgeeks'}by
Difference between call by value and call by reference:
Call by value | Call by reference |
The original variable is not modified on changes in other variables. | The original variable gets modified on changes in other variables. |
Actual and copied variables will be created in different memory locations. | Actual and copied variables are created in the same memory location. |
On passing variables in a function, any changes made in the passed variable will not affect the original one. | On passing variables in a function, any changes made in the passed parameter will update the original variable’s reference too. |
pass by value & pass by reference
미숙한 해석... 근데 Pass By Value가 이해가 안 돼서 며칠내내 머리에 쥐나면서 구글을 뒤젹였던 게 원문을 보니 이해가 딱 됐다.. 원문 찾아보는 습관을 들여야 겠다.
Pass By Value에서 함수는 전달인자(argument)로서의 변수의 값을 직접적으로 지나가면서 호출이 된다. 그러므로 함수 속 어떠한 변화도 기존의 값에 영향을 미치지 않는다. 매개변수들(parameters)은 이 전달인자들이 스스로의 복사본을 만들어낼 때 통과가 된다. 그러므로 함수 속 어떠한 변화도 복사본에 대한 것이지 기존값에 대한 것이 아니다.
함수는 매개변수로 정해진 자리와 규칙 속에서 역할놀이를 한 후 값을 리턴하고(리턴을 요구할 때) 룰루랄라 사라지는 구나! (나만의 언어로 이해 ㅋㅋㅋㅋㅋㅋㅋㅋ) 드디어 이해했다 가릿짜릿!!!!!! ㅠㅠ
아래 원문 참고.
Pass By Value: In Pass by value, function is called by directly passing the value of the variable as an argument. So any changes made inside the function does not affect the original value.
In Pass by value, parameters passed as an arguments create its own copy. So any changes made inside the function is made to the copied value not to the original value .
Let us take an example to understand better:
function Passbyvalue(a, b) {
let tmp;
tmp = b;
b = a;
a = tmp;
console.log(`Inside Pass by value
function -> a = ${a} b = ${b}`);
}
let a = 1;
let b = 2;
console.log(`Before calling Pass by value
Function -> a = ${a} b = ${b}`);
Passbyvalue(a, b);
console.log(`After calling Pass by value
Function -> a =${a} b = ${b}`);
|
Output:
Before calling Pass by value Function -> a = 1 b = 2
Inside Pass by value function -> a = 2 b = 1
After calling Pass by value Function -> a =1 b = 2
Pass by Reference: In Pass by Reference, Function is called by directly passing the reference/address of the variable as an argument. So changing the value inside the function also change the original value. In JavaScript array and Object follows pass by reference property.
In Pass by reference, parameters passed as an arguments does not create its own copy, it refers to the original value so changes made inside function affect the original value.
let us take an example to understand better.
function PassbyReference(obj) {
let tmp = obj.a;
obj.a = obj.b;
obj.b = tmp;
console.log(`Inside Pass By Reference
Function -> a = ${obj.a} b = ${obj.b}`);
}
let obj = {
a: 10,
b: 20
}
console.log(`Before calling Pass By Reference
Function -> a = ${obj.a} b = ${obj.b}`);
PassbyReference(obj)
console.log(`After calling Pass By Reference
Function -> a = ${obj.a} b = ${obj.b}`);
|
Output:
Before calling Pass By Reference Function -> a = 10 b = 20
Inside Pass By Reference Function -> a = 20 b = 10
After calling Pass By Reference Function -> a = 20 b = 10
Note: In Pass by Reference, we are mutating the original value. when we pass an object as an arguments and update that object’s reference in the function’s context, that won’t affect the object value. But if we mutate the object internally, It will affect the object .
Example 1: Updating the object reference in the function.
function PassbyReference(obj) {
// Changing the reference of the object
obj = {
a: 10,
b: 20,
c: "GEEKSFORGEEKS"
}
console.log(`Inside Pass by
Reference Function -> obj `);
console.log(obj);
}
let obj = {
a: 10,
b: 20
}
console.log(`Updating the object reference -> `)
console.log(`Before calling Pass By
Reference Function -> obj`);
console.log(obj);
PassbyReference(obj)
console.log(`After calling Pass By
Reference Function -> obj`);
console.log(obj);
|
Output:
Updating the object reference ->
Before calling PassByReference Function -> obj
{a: 10, b: 20}
Inside PassbyReference Function -> obj
{a: 10, b: 20, c: "GEEKSFORGEEKS"}
After calling PassByReference Function -> obj
{a: 10, b: 20}
Example 2: Mutating the original Object.
function PassbyReference(obj) {
// Mutating the original object
obj.c = "GEEKSFORGEEKS";
console.log(`Inside Pass by
Reference Function -> obj `);
console.log(obj);
}
let obj = {
a: 10,
b: 20
}
console.log(`Mutating the original object -> `)
console.log(`Before calling Pass By
Reference Function -> obj`);
console.log(obj);
PassbyReference(obj)
console.log(`After calling Pass By
Reference Function -> obj`);
console.log(obj);
|
Output:
Mutating the original object ->
Before calling PassByReference Function -> obj
{a: 10, b: 20}
Inside PassbyReference Function -> obj
{a: 10, b: 20, c: "GEEKSFORGEEKS"}
After calling PassByReference Function -> obj
{a: 10, b: 20, c: "GEEKSFORGEEKS"}
참고
https://www.geeksforgeeks.org/call-by-value-vs-call-by-reference-in-javascript/
https://www.geeksforgeeks.org/pass-by-value-and-pass-by-reference-in-javascript/
https://www.javascripttutorial.net/javascript-pass-by-value/
'FE > JavaScript' 카테고리의 다른 글
[JS] test를 통한 object 개념 익히기 _Koans (0) | 2023.03.06 |
---|---|
[JS] this (0) | 2023.03.06 |
[JS] test를 통한 화살표 함수 개념 익히기 _Koans (0) | 2023.03.05 |
[JS] test를 통한 const 개념 익히기 _Koans (0) | 2023.03.05 |
[JS] test를 통한 type 개념 익히기 _Koans (2) | 2023.03.05 |