22. 고급테크닉

· ☕ 4 min read · 👀... views

다루는 내용

  1. 고급 함수
  2. 쉽게 조작할 수 없는 객체
  3. 타이머 조작
  4. 커스텀 이벤트

1. 고급 함수

  • 단순한 절차적인 방식, 복잡하고 동적인 방식, 클로저, 함수 포인터 등을 사용하는 다양성

1.1 안전한 타입 탐지

  • typeof 나 instanceof 처럼 내장된 타입 탐지는 완벽하지 않음

  • Object 의 toString() 메소드를 이용

    1
    2
    3
    
    Object.prototype.toString.call(value) == "[object Function]"
      
    window.JSON && Object.prototype.toString.call(JSON) == "[object JSON]"
    

1.2 스코프 확인 생성자 (scope-safe constructor)

  • new 연산자 없이 객체를 생성하면 this 가 전역에 묶여버리는 문제가 있음

    1
    2
    3
    4
    5
    6
    7
    8
    
    function Person(name, age) {
      if(this instanceof Person) {
        this.name = name;
        this.age = age;
      } else {
        return new Person(name, age)
      }
    }
    
    • if/else 를 통해 해결
  • 생성자 훔치기 패턴을 사용할 때에는 프로토 타입 체인이나, 기생 상속을 함께 사용 자세한 내용은 (6장. 객체지향 프로그래밍 참조)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    function Polygon(sides) {
      if(this instanceof Polygon) {
        this.sides = sides;
        this.getArea = function() {
          return 0;
        };
      } else {
        return new Polygon(sides);
      }
    }
      
    function Rectangle(width, height) {
      Polygon.call(this, 2);
      this.width = width;
      this.height = height;
      this.getArea = function() {
        return this.width * this.height;
      };
    }
      
    Rectangle.prototype = new Polygon();
      
    var rect = new Rectangle(5, 10);
    console.log(rect.sides); // 2
    

1.3 지연 로딩 함수

  • 브라우저 차이 때문에 if 문이 많은데, if 문은 단 하나만 존재해도 속도에 영향을 줄 수 있기 때문에 if 문을 필요할 때만 실행하도록 하는게 권장되고 이를 지연로딩 이라고 함

    1. 함수를 처음 호출할 때 자기 자신을 수정하도록 만드는 방법
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    function createA() {
      if(typeof request != "undefined") {
        createA = function() {
          return new Request();
        }
      } else {
        ...
      }
        return createA()
    }
    
    1. 적절한 함수를 선언하는 즉시 다른 함수를 할당하는 방법
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    var createA = (function() {
      if(typeof request != "undefined") {
        return function() {
          return new Request();
        }
      } else {
        ...
      }
    })();
    

1.4 함수 바인딩

  • 특정한 this 값과 특정한 매개변수를 넘기면서 다른 함수를 호출하는 함수

  • 참조 apply, call, bind 에 대해

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    var handler = {
      message: "event",
      handleClick: function(event) {
        console.log(this.message + ":" + event.type);
      }
    };
      
    var btn = document.getElementById("btn");
    var bbtn = btn.bind(hadler);
    

1.5 함수 커링

  • 커링은 단순히 감쌀 함수만 받지만, bind 는 함수와 context 객체를 함께 받음

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    function add(num1, num2) {
      return num1 + num2;
    }
      
    function curry(num3) {
      return add(5, num3);
    }
      
    add(2,3); // 5
    curry(3); // 8
    

2. 쉽게 조작할 수 없는 객체

  • 컨텍스트가 같으면 수정하지 못하게 막을 방법이 없음
  • 일단 객체를 쉽게 조작할 수 없는 객체로 바꾸고나면 이를 취소할 수 없음

2.1 확장 불가능한 객체

  • Ojbect.preventExtension() 를 통해 프로퍼티나 메소드를 추가할 수 없게 만듦
  • 맴버를 수정하거나 삭제는 가능
  • Object.isExtensible() 을 통해 확장 여부 확인 가능

2.2 봉인된 객체

  • Object.seal() 메소드를 사용하며 [[configurable]] 속성이 false 가 됨
  • Object.isSealed() 를 통해 봉인 여부 확인 가능

2.3 동결된 객체

  • wirte 조차 불가능한 가장 강력한(?) 객체 ([[set]] 이 지정된 경우만 수정 가능 )
  • Object.freeze() 를 통해 동결

3. 고급 타이머

  • setTimeout() 이나 setInterval() 로 타이머를 생성하여 유용한 기능을 만들 수 있지만, 이들은 스레드이며 자바스크립트는 단일 스레드 환경에서 동작함
  • 자바스크립트에서 즉시 실행되는 코드는 존재하지 않음. 모든 코드는 일단 큐에 추가되었다가 실행이 됨
  • 타이머를 15초로 설정하면 코드가 15초 뒤에 실행되는 것이 아니라 15초 뒤에 큐에 추가 되는 것

3.1 타이머 반복

  • setInterval() 을 사용해 주기적으로 타이머 코드를 큐에 추가 가능

  • 타이머 코드가 실행되기 전에 큐에 코드를 삽입할 가능성이 있기 때문에 다른 인스턴스가 큐에 존재하지 않을 때만 추가 하지만, 여기에는 2가지 단점이 있음

    1. 실행되지 않는 구간이 생길 수 있음
    2. 코드 사이의 갭이 예상보다 작을 경우 타이머 코드를 건너뛰게 됨
  • 2번의 경우를 피하려면 setTimeout() 을 재귀호출 해야함

    1
    2
    3
    4
    5
    6
    
    setTimeout(function() {
      // sth..
        
      setTimeout(arguments.callee, 50);
       
    }, 50);
    

3.2 프로세스 관리

  • 브라우저는 코드가 일정 시간 이상 실행되거나 일정 숫자 이상의 문장을 실행하지 못하도록 오래 사용되는 스크립트 를 제한 함

  • 오래 실행되는 루프의 경우 배열 나누기를 통해 사용자 인터페이스가 잠기는 것을 방지할 수 있음

    1
    2
    3
    4
    5
    6
    7
    8
    
    setTimeout(function() {
      var item = array.shift();
      process(item);
        
      if(array.length > 0) {
        setTimeout(arguments.callee, 100);
      }
    }, 100)
    

3.3 함수 감속

  • 짧은 시간 동안 DOM 조작을 너무 많이 하면 브라우저가 멈추기에 타이머를 이용해 감속으로 완화하는 목적

    1
    2
    3
    4
    5
    6
    
    function throttle(method, context) {
      clearTimeout(method.tId);
      methid.tId = setTimeout(function() {
        method.call(context);
      }, 100);
    }
    
  • resize 같이 코드를 주기적으로 실행해야 하지만 호출 자체를 제어할 수 없을 때 사용

4. 커스텀 이벤트

  • 이벤트는 옵저버 패턴의 일종인데, 코드를 느슨하게 연결하는 테크닉
  • 주체는 이벤트가 일어났음을 알리고, 옵저버는 이들 이벤트를 주시하며 주체를 관찰하기만 함
  • 기본 아이디어는 이벤트를 관리하는 객체를 만들고 다른 객체가 그 이벤트를 주시하게 하는 것
  • 커스텀 이벤트를 사용하면 관련된 객체를 분리하고 기능을 격리하기 쉬움
Share on

snack
WRITTEN BY
snack
Web Programmer


What's on this Page