개발자가 되어보자

[Weekly Paper] 3. 동등 연산자(==) VS 일치 연산자(===) & 복사 본문

Codeit/Weekly Paper

[Weekly Paper] 3. 동등 연산자(==) VS 일치 연산자(===) & 복사

HVIN 2023. 11. 5. 05:00

동등 연산자(==) vs 일치 연산자(===)

  • 동등 연산자(==)
    • 두 개의 피연산자가 동일한지 확인하여 boolean 결과를 반환한다
    • 다른 타입의 피연산자들끼리의 비교를 시도한다 = 두 피연산자를 느슨하게 비교한다(타입이 다르면 형변환을 시도해 일치할 경우 true 반환)
    • 동일한 타입일 때 비교
      • 객체 : 두 피연산자가 동일한 객체를 참조하는지
      • 문자열 : 두 피연산자가 동일한 문자를 동일한 순서로 가지는지
      • 숫자 : 두 피연산자가 동일한 값을 가지는지. 두 피연산자가 모두 NaN이라면 false
      • 불리언 : 두 피연산자가 모두 true이거나 모두 false일 때만 true
      • BigInt : 두 피연산자가 동일한 값을 가지는지
      • 심볼 : 두 피연산자가 동일한 심볼을 참조하는지
    • null과 undefined를 비교할 경우 true를 반환한다
    • 하나의 피연산자가 객체이고 다른 하나가 원시 타입인 경우, 객체를 원시 타입으로 변환한다
      • 두 피연산자를 모두 원시 타입(문자열, 숫자, 불리언, 심볼, BigInt) 중 하나로 변환한다
      • 하나의 피연산자가 심볼이고 다른 하나가 심볼이 아닌 경우, false
      • 하나의 피연산자가 불리언이고 다른 하나가 불리언이 아닌 경우 불리언을 숫자로 변환한다 → 그 후 두 피연산자를 다시 느슨하게 비교한다
      • 숫자와 문자열을 비교할 때 문자열을 숫자로 변환한다 → 변환 실패의 결과값은 NaN이므로, 비교 결과가 false라는 것을 보장한다
      • 숫자와 BigInt는 숫자 값으로 비교한다 → 숫자가 ±Infinity 혹은 NaN이면 false를 반환한다
      • 문자열과 BigInt는 문자열을 BigInt() 생성자와 같은 알고리즘으로 BigInt로 변환한다. 변환이 실패하면 false를 반환한다
  • 일치 연산자(===)
    • 두 피연산자가 동일한지 확인하여 boolean타입 결과를 반환한다
    • 동등 연산자와 달이 엄격하게 비교하여 다른 타입의 피연산자들은 항상 다른 것으로 간주한다
    • 두 피연산자 중 하나가 NaN이면 false를 반환한다
    • 일치 연산자에서 null과 undefined은 다르다 → null과 undefined를 비교할 경우 false를 반환한다

Javscript에서의 복사(Copy)

    • 자바스크립트에서 원시값을 복사하려고 할 때는 새로운 변수를 선언해 복사하고자 하는 값을 할당해주면 된다
let a = 1;
let b = a; 

console.log(a); // 1
console.log(b); // 1

b = 3;

console.log(a); // 1
console.log(b); // 3
  • 객체 또는 배열을 복사하기 위해 새로운 배열이나 객체를 선언하고 원래 있던 배열이나 객체를 할당하면 값을 복사하는 것이 아니라 참조를 복사하는 것(주소 복사)이기 때문에 복사본을 수정할 경우 원본에도 변경 사항이 생긴다
  • 이를 해결하기 위한 여러 방법이 있는데 그 방법들도 얕은 복사와 깊은 복사로 나뉜다
  • 얕은 복사(Shallow Copy)
    • 주로 원본 객체 또는 배열의 내용을 다른 객체 또는 배열에 복사한다 → 원본과 복사본은 서로 다른 객체를 가리킨다
    • 그러나 내부 객체나 배열은 복사되지 않고 참조만 복사한다 → 내부 객체의 변경은 원본과 복사본 양쪽에 모두 영향을 끼친다
        • 배열이 2차원 이상이거나 객체 속의 객체일 경우 복사가 제대로 되지 않는다
        • 객체 내부의 값들 중 원시값들은 복사본에서 수정을 해도 영향을 받지 않지만 내부의 값 중 객체가 있을 경우 해당 객체는 복사본이 수정될 경우 원본도 같이 값이 변경된다
      // 객체의 얕은 복사
      const originalObj = { a: 1, b: { c: 2 } };
      const shallowCopyObj = Object.assign({}, originalObj);
      
      console.log(originalObj.b.c); // 2
      
      shallowCopyObj.b.c = 3; // 원본 객체의 내부 객체도 변경됨
      
      console.log(shallowCopyObj.b.c); // 3
      console.log(originalObj.b.c); // 3
      
      // 배열의 얕은 복사
      const originalArray = [1, [2, 3]];
      const shallowCopyArray = [...originalArray];
      
      console.log(originalArray[1][0]); // 2
      
      shallowCopyArray[1][0] = 4; // 원본 배열의 내부 배열도 변경됨
      
      console.log(shallowCopyArray[1][0]); // 4
      console.log(originalArray[1][0]); // 4
    • 주로 객체와 배열의 복사에 사용한다 → 객체 내부에 원시값만 있는 객체나 일차원 배열을 복사할 때 사용하는 것이 좋다
    • 얕은 복사를 수행하는 방법
        • 객체 병합(Object.assign()
        • 스프레드 연산자(…))
        • 배열 병합(배열 스프레드 연산자 또는 배열의 slice() 메서드)
      // 객체의 얕은 복사
      const originalObj = { a: 1, b: 2 };
      const shallowCopyObj = Object.assign({}, originalObj);
      
      // 배열의 얕은 복사
      const originalArray = [1, 2, 3];
      const shallowCopyArray = [...originalArray];
  • 깊은 복사(Deep Copy)
      • 원본 객체나 배열 및 그 안에 중첩된 객체와 배열까지 모두 완전히 복사한다 → 원본과 복사본은 서로 독립된 객체 또는 배열이 되고 내부 객체의 변경이 서로에게 영향을 주지 않는다
      • 깊은 복사를 수행하기 위해서는 재귀적으로 객체와 배열의 내부 요소를 순회하고 복사하는 과정이 필요하다
      • 직접 구현하거나, Lodash와 같은 라이브러리 사용 또는 JSON.stringify() 및 JSON.parse()를 사용하여 쉽게 수행할 수 있다
    // Lodash를 사용한 깊은 복사
    const _ = require('lodash');
    const originalObj = { a: 1, b: { c: 2 } };
    const deepCopyObj = _.cloneDeep(originalObj);
    
    console.log(originalObj.b.c); // 2
    
    deepCopyObj.b.c = 3; // 원본 객체의 내부 객체는 변경되지 않음
    
    console.log(deepCopyObj.b.c); // 3
    console.log(originalObj.b.c); // 2
    
    // JSON.stringify()와 JSON.parse()를 사용한 깊은 복사
    const originalArray = [1, [2, 3]];
    const deepCopyArray = JSON.parse(JSON.stringify(originalArray));
    
    console.log(originalArray[1][0]); // 2
    
    deepCopyArray[1][0] = 4; // 원본 배열의 내부 배열은 변경되지 않음
    
    console.log(deepCopyArray[1][0]); // 4
    console.log(originalArray[1][0]); // 2
  • 얖은 복사는 성능상 이점이 있지만 중첩된 데이터를 다룰 때 문제가 발생할 수 있다
  • 깊은 복사는 데이터의 완전한 분리를 보장하지만 성능 면에서 얕은 복사보다 느릴 수 있으며, 무한 루프와 같은 잠재적인 문제를 다루는 데 주의가 필요하다
  • 복사를 하려고 할 때 데이터 구조와 동작을 고려해 얕은 복사 또는 깊은 복사를 선택해야 한다
Comments