JavaScript에서 모든 메서드를 연결 가능하게 만드는 방법

TLDR;


  • jQuery가 웹과 JavaScript를 앞으로 밀었지만 해당 메서드 연결이 크게 누락되었습니다.

  • 이것을 되돌릴 수 있는 방법이 있다고 말하면 어떻게 될까요?
  • 이것은 제가 여기에서 이야기하려고 하지 않은 것을 나타내는 것일 수 있습니다 👀

  • 왜 누군가가 이것에 관심을 가져야 합니까?



    JavaScript에 대한 경험과 상관없이 jQuery에 대해 들어본 적이 있을 것입니다. 2000년대 초중반 동안 웹은 개발자가 웹 페이지 모음에 비해 유동적인 사용자 경험을 만들 수 있는 성숙도 수준에 도달했습니다.

    하지만 자바스크립트와 웹 브라우저 API가 다른 프로그래밍 언어와 비교했을 때 이 작업은 지루한 작업이었습니다. fetch 또는 document.querySelector 가 없다고 상상해보십시오. 꽤 거칠죠? 글쎄요, jQuery는 모든 공백을 채웠고 그 다음에는 일부를 채웠습니다. 일부에게 jQuery는 클라이언트 측 웹 개발의 표준 라이브러리였습니다. 그러나 그것은 그때였습니다. JavaScript and the web has evolved .

    그러나 JavaScript 및 웹 API를 향상시키는 모든 중요한 개선 사항과 함께 jQuery's method chaining was largely left behind . 그리고 이것 때문에 jQuery isn't leaving the tool-belt of some developers . 그들을 비난할 수 있습니까? jQuery는 깨끗한 개발자 경험을 제공하면서 유사하게 깨끗한 사용자 경험을 구축하기 위한 도구를 제공했습니다. 이것을 되돌릴 수 있는 비교적 빠르고 고통 없는 방법은 무엇입니까?

    메소드 체이닝이란?




    $("#p1").css("color", "red").slideUp(2000).slideDown(2000);
    

    .css , .slideUp , slideDown 와 같은 연결 방법은 표현력이 뛰어나고 간결합니다. jQuery's implementation represents a Fluent Interface , 코드가 거의 일반 영어처럼 읽히는 expressiveness 수준을 제공합니다.

    네이티브 메소드 체이닝은 깔끔하지 않을까요?




    document.querySelector("#p1")
      .setCss({ transition: 'height 2s', height: '0px' })
      .setCss({ height: '100px' });
    


    이것은 달성할 수 있지만 one would need to know and care about implementation details between the DOM and one's app 대부분의 사용 사례에 필요한 것보다 훨씬 더 복잡할 수 있습니다.

    상자를 사용한 일반 메서드 체이닝 소개




    Box(document.getElementById('p1'))
        .modifyContents(slideUp(2000))
        .modifyContents(slideDown(2000, '100px'));
    


    목표는 원하는 것을 상자 안에 넣는 것입니다. 두 가지 방법replaceContentsmodifyContents를 사용하면 일시적으로 항목을 상자 외부로 가져와 작업을 수행하고 다른 상자에 넣을 수 있습니다.

    이 접근 방식을 사용하면 원하는 것(메서드 연결)과 이미 작성 중인 것(DOM 조작)을 명확하게 구분할 수 있습니다. 또한 고도로 모듈화된 독립적인 코드를 작성하고 테스트하기가 더 쉽습니다.

    import { Box } from './box' // highly modular
    import { slideUp, slideDown } from './dom' // bring your own implementation details
    


    이 메서드 체인 형식이 정말 일반적입니까?



    번호




    const four = Box(4);
    const eight = four
      .replaceContents((num) => num * 2)
      .modifyContents(console.log); // 8
    
    const ten = eight
      .replaceContents((num) => num + 2)
      .modifyContents(console.log); // 10
    


    배열




    const nums = Box([1, 2, 3, 4, 5]);
    const evens = nums
      .replaceContents((numArr) => numArr.map((x) => x + 2))
      .modifyContents(console.log) // [3, 4, 5, 6, 7]
      .replaceContents((sums) => sums.filter((x) => x % 2 === 0))
      .modifyContents(console.log); // [4, 6]
    


    혼합 유형(맵, 배열)




    const gteTo2 = Box(new Map([["a", 1], ["b", 2], ["c", 3]]))
      .replaceContents((table) => [...table.entries()])
      .replaceContents((arr) => arr.filter(([, value]) => value >= 2))
      .replaceContents((arr) => new Map(arr))
      .modifyContents(console.log); // Map { 'b' => 2, 'c' => 3 }
    


    예!

    상자는 모든 유형에서 작동합니다. 두 가지 방법replaceContentsmodifyContents에는 단일 매개변수가 있으며, 이는 상자 안에 있는 항목이 무엇이든 상관없습니다.

    상자는 프리미티브 또는 객체를 포함할 수 있습니다. 두 메서드의 차이점은 replaceContents는 값을 반환해야 하고 modifyContents는 반환하지 않는다는 것입니다. 즉, replaceContents는 불변성을 보장하는데 좋습니다.

    TypeScript 또는 다른 언어에 대한 인터페이스는 다음과 같습니다.

    interface IBox<T> {
      replaceContents: <V>(fn: (item: T) => V) => IBox<V>;
      modifyContents: (fn: (item: T) => void) => IBox<T>;
    }
    


    Box는 Fluent Interfaces와 어떻게 비교됩니까?





    상자
    유창한 인터페이스


    메소드 체이닝



    높은 표현력



    불변성 지원



    디버거 친화적



    로깅 친화적



    모든 데이터 유형에서 작동



    모듈 친화적




    판매된? 상자의 모양은 다음과 같습니다.




    function Box(item) {
        const replaceContents = (fn) => Box(fn(item));
        const modifyContents = (fn) => {
            fn(item);
            return Box(item);
        };
        return { replaceContents, modifyContents };
    };
    


    잠깐만, 상자는 당신이 알고 있는 것입니까?



    👀

    좋은 웹페이지 즐겨찾기