JS 리팩토링 주의 사항: 옵셔널 체이닝으로 변환하면 코드가 깨질 수 있는 5가지 방법

optional chaining 연산자.?는 개체를 사용할 수 있을 때 개체 속성 값을 반환하고 그렇지 않으면 undefined를 반환합니다. 표준. 연결 연산자와 유사하며 개체가 정의되어 있는지(즉, nullish 아님) 확인이 추가되었습니다.

선택적 연결 연산자를 사용하면 연결된 개체 중 일부가 null 또는 undefined 일 수 있는 경우 연결된 개체의 간결하고 안전한 체인을 작성할 수 있습니다. ES2020에 optional chaining이 도입되기 전에 && 연산자는 객체가 사용 가능한지 확인하는 데 자주 사용되었습니다( obj && obj.value ).

선택적 연결 패턴을 사용하여 기존 검사를 종종 단순화할 수 있습니다.
  • obj && obj.propertyobj?.property가 된다
  • obj != null && obj.propertyobj?.property가 된다
  • obj != null ? obj.property : undefinedobj?.property가 된다
  • arr && arr[i]arr?.[i]가 된다
  • f && f()f?.()가 된다
  • 기타

  • 그러나 옵셔널 체이닝으로 리팩토링하면 버그가 발생할 수 있는 몇 가지 경우가 있습니다.

    null 값에 대한 선택적 연결 단락(다른 거짓 값에는 해당되지 않음)


    a && a.ba?.b로 대체되면 falsy 값을 가질 수 있는 유형에 대한 실행이 변경됩니다. 이는 결과 값과 식의 유형이 선택적 연결과 다를 수 있음을 의미합니다.

    다음 스니펫은 몇 가지 예를 보여줍니다.

    function test(value) {
        console.log(`${value && value.length}, ${value?.length}`);
    }
    
    test(undefined);       // undefined, undefined
    test(null);            // null, undefined
    test(true);            // undefined, undefined
    test(false);           // false, undefined
    test(1);               // undefined, undefined
    test(0);               // 0, undefined
    test({});              // undefined, undefined
    test([]);              // 0, 0
    test({ length: "a" }); // a, a
    test('');              // , 0
    test(NaN);             // NaN, undefined
    


    거짓이지만 nullish 이 아닌 빈 문자열은 특히 문제가 될 수 있습니다. 다음은 선택적 연결을 도입하여 문제를 일으킬 수 있는 예입니다.

    // without optional chaining
    if (s && s.length === 0) {
      // not called for the empty string 
      // (e.g., legacy code that works this way)
    }
    
    // with optional chaining
    if (s?.length === 0) {
      // called for the empty string 
      // (potentially introducing undesired behavior)
    }
    


    선택적 연결은 null에 대한 결과를 정의되지 않음으로 변경합니다.



    null로 a?.b를 호출하면 결과는 undefined입니다. 그러나 a && a.b 의 경우 결과는 null 입니다.

    선택적 연결은 부작용이 있는 호출 수에 영향을 줄 수 있습니다.



    예를 들어 변경을 고려하십시오.

    f() && f().a;
    


    ~ 안으로

    f()?.a;
    

    && 로 , f 를 한두 번 호출합니다. 그러나 선택적 연결f을 사용하면 한 번만 호출됩니다. f에 부작용이 있는 경우 이 부작용이 다른 횟수로 호출되어 잠재적으로 동작이 변경되었을 수 있습니다. 이 동작은 함수 및 메서드 호출뿐만 아니라 잠재적으로 부작용이 있을 수 있는 getter에도 적용됩니다.

    TypeScript는 'void' 유형의 선택적 연결을 지원하지 않습니다.



    TypeScript does not support optional chaining for void , 해당 JavaScript 코드가 작동하더라도 이벤트가 발생합니다.

    type Input = void | {
        property: string
    };
    
    function f(input: Input) {
        // this works:
        console.log(input && input.property);
        // this breaks because void is not undefined in TypeScript:
        console.log(input?.property);
    }
    


    이전 브라우저 및 JavaScript 엔진은 선택적 연결을 지원하지 않습니다.



    선택적 연결은 ES2020 기능입니다. 모든 최신 브라우저 및 Node 14+에서 지원되지만 이전 브라우저 및 Node 버전의 경우 변환이 필요할 수 있습니다( compatibility ).

    좋은 웹페이지 즐겨찾기