Fall in IT.

자바스크립트 프로토타입, 클로저, 디바운싱 알아보기 본문

프로그래밍언어/Javascript & Typescript

자바스크립트 프로토타입, 클로저, 디바운싱 알아보기

D.Y 2018. 5. 26. 23:21
자바스크립트 기본 개념 알아보기2

1. 프로토타입
- 모든 객체는 속성을 상속하는 프로토타입 객체에 연결돼 있습니다. 객체 리터럴로 생성되는 모든 객체는 자바스크립트의 표준 객체인 Object의 속성인 prototype 객체에 연결됩니다. 

프로토타입 연결은 오로지 객체의 속성을 읽을 때만 사용합니다. 객체에 있는 특정 속성의 값을 읽으려고 하는데 해당 속성이 객체에 없는 경우 자바스크립트는 이 속성을 프로토타입 객체에서 찾으려고 합니다. 이러한 시도를 프로토타입 체이닝이라고 합니다. 가장 마지막에 있는 Object.prototype까지 계속해서 이어집니다. 

만약 찾으려는 속성이 프로토타입 어디에도 존재하지 않는 경우 undefiend를 반환합니다.

- 자바스크립트에서는 상속이라는 개념을 프로토타입을 이용하여 구현할 수 있다. 
- 프로토타입을 활용해서 배열, String, Number 등(즉, Object)을 확장도 가능하다. 

ex) 간단 프로토타입을 사용한 상속
function Person(name) {
     this.name = name;
     this.introduce = function() {
          return 'My name is ' + this.name;
     }
}

var person1 = new Person('dylee');

==========================================

function Person2(name) {
     this.name = name;
}
Person2.prototype.name = null;
Person2.prototype.introduce = function() {
     return 'My name is ' + this.name;
}

var person2 = new Person2('person');


function Programmer(name) {
     this.name = name;
}
Programmer.prototype = new Person2();
var person3 = new Programmer('programmer');

ex) 프로토타입 체이닝 & 상속
var stooge = {
"name": "Jhon",
"age": 29
}

var another_stooge = Object.create(stooge);
console.log(another_stooge.name); // Jhon
console.log(another_stooge.age); // 29

stooge.height = 180;
console.log(another_stooge.height); // 180

ex2) 프로토타입 체이닝 & 상속
function Ultra() {}
Ultra.prototype.ultraProp = true; 
console.log(Ultra.prototype.ultraProp); //true

function Super() {}
Super.prototype = new Ultra();

function Sub() {}
Sub.prototype = new Super();
Sub.prototype.ultraProp = 1; //ultraProp 오버라이딩

var o = new Sub();
console.log(o.ultraProp); //1 


프로토타입을 사용하여 Object 확장하기
Object.prototype.contain = function(needle) {
for(var name in this) {
// 모든 객체에 contain이 추가되었기 때문에 for-in 문에서 조심해서 사용해야 한다.
console.log(name);
if(this[name] === needle) {
return true;
}
}
return false;
}

var o = {'name': 'aaa'};
console.log(o.contain('aaa')); //true
var a = ['aaa', 'bbb', 'ccc'];
console.log(a.contain('aaa')); //true



2. 클로저
- 클로저는 이너함수가 스코프 밖에 있는 변수에 접근하는 것입니다. 클로저는 정보은닉을 구현하거나 함수 팩토리를 생성할때 사용됩니다.
- 내부함수가 외부함수의 맥락(Context)에 접근할 수 있는 것을 가르킨다.

// ex) 정수로 이루어진 배열을 반복문으로 접근하여 해당 요소마다 3초를 지연시키고 출력하기
const arr = [1,2,3,4];
for(var i = 0; i < arr.length; i++) {
  setTimeout(function() {
    console.log(arr[i]);
  }, 3000);
}

// 방법1
for(var i = 0; i < arr.length; i++) {
  setTimeout(function(i) {
    return function() {
      console.log(arr[i]);
    }
  }(i), 3000);
}

// 방법2
for(let i = 0; i < arr.length; i++) {
  setTimeout(function() {
    console.log(arr[i]);
  }, 3000);
}

// ex) factory_movie메소드의 매개변수인 title이 외부에서 접근이 허용되지 않게 하기위해서 사용되는 방법
// title은 get_title함수와, set_title 함수를 사용해서 접근이 가능하다. 정보은닉 효과가 있다.
function factory_movie(title) {
     return {
          get_title: function() {
              return title;
          },
          set_title: function(_title) {
              title = _title;
          }
     }
}



3. 디바운싱(Debouncing) 또는 쓰로틀링(Throttling)
- 키워드 검색 자동완성, 스크롤링 등에 사용.
- 문제: 사용자가 키보드를 누를때마다 서버에 쿼리를 하고 받아온 데이터를 binding하여 화면에 뿌려준다고 할 경우, 빠르게 입력하면 할수록 버벅임이 많이 생기게 될것입니다. 스크롤을 감지하기위해 스크롤 이벤트 핸들러에 이벤트를 거는것도 마찬가지.
- 해결방법: 실제 함수가 호출되는 시점을 조정합니다. 입력이 완료되고 일정시간 간격후에 이벤트가 동작하도록 구현합니다. 이를 디바운싱이라고 합니다.

// 이벤트를 감쌀 디바운싱 함수
function debounce(fndelay) {
  // 타이머 선언
  let timer = null;
  // 타이머 변수에 접근 가능한 클로져 함수

  return function() {
    // 클로져 함수 안에서 this 와 arguments 변수로 디바운싱 함수의 스코프와 변수를 접근한다.
    let context = this;
    let args = arguments;
    // 만약 이벤트가 호출되면 타이머를 초기화 하고 다시 시작한다.
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(context, args);
    }, delay);
  };
}

function debounce2(funcdelay) {
  setTimeout(func, delay);
} // 안되는 이유는 mdn에 setTimeout 내용 참고.

function foo() {
  console.log('you are scrolling');
}

window.addEventListener('scroll', debounce(foo, 2000)); // 정상동작
window.addEventListener('scroll'debounce2(foo, 2000)); // 동작안함





4. 자바스크립트 문서의 로드 시점
// 문서의 모든 콘텐츠(images, script, css 등)가 로드된 후 발생하는 이벤트
// 반드시 동일한 문서에는 하나만 선언되어야 한다.
window.onload = function() {
  console.log("window.onload");
};

// html과 script가 로드된 시점에 발생하는 이벤트
// onload 보다 먼저 발생. IE8 이하에서는 지원하지 않음.
window.addEventListener("DOMContentLoaded", function() {
  console.log("DOMContentLoaded");
});



Comments