# 퀴즈

sykim·2020년 5월 1일
0

자바스크립트

목록 보기
1/6

사전 퀴즈

  1. 위의 코드를 실행하면 무엇이 출력되나요? *

정답은 '오류가 발생한다'
apply, call, bind 등으로 this에 대해 주입한 상황이 아니고 new 키워드없이 실행한 함수 내 this는 전역 객체(window)를 바라본다.
즉 this.name = name의 결과는 window.name = name 이라는 이야기이다.
의도한 결과가 나오면 new Cat으로 인스턴스를 생성하여 this가 해당 인스턴스를 가리키도록 해야 한다.


  1. 위의 코드를 실행하면 무엇이 출력되나요? *

    hello roto가 출력된다.
  • ` 감싼 문자열은 ES6에 있는 template strings라는 문법이다.
  • 즉시 실행 함수 표현(IIFE, Immediately Invoked Function Expression)이라고 하며, 함수를 선언함과 동시에 실행한다.
  • JavaScript 특성상 변수의 scope는 해당 변수를 감싸고 있는 function에 한정되는데, 이걸 이용해 변수나 함수의 전역화를 최소화 시킬 수 있다.
    다음은 대표적인 IIFE의 응용이다.
var logger = (function(){
  // logCount는 밖에서 접근할 수 없다. 일종의 private 효과
  var logCount = 0;
  function log(message) {
    console.log(message);
    logCount = logCount + 1;
  }
  function getLogCount() {
    return logCount;
  }
  return {
    log: log,
    getLogCount: getLogCount
  }
})() 

=> logger만 window에 묶이고 내부에 있는 변수나 함수는 바깥에서 접근하지 않는다. (스코프의 오염 방지)


  1. 위의 코드를 실행하면 무엇이 출력되나요? *

    function scope 관련 문제
    정답은 band undefined roto play start. 출력
    play 함수의 this 내에는 name이 없기 때문에 undefined가 출력 되는 것
    해결법
var idiots = {
  name: 'idiots',
  genre: 'punk rock',
  members: {
    roto: {
      memberName: 'roto',
      play: function() {
        console.log(`band ${idiots.name} ${this.memberName} play start.`
      } 
    }
  }
}


  1. 맨 아래 theOralCigarettees.perform()을 실행하는 게 빠졌네요..

perform 함수 아래 setTimeout으로 인해 실행되는 함수의 this는 RockBand의 this가 아니기 때문에, 참조 오류가 발생
클로저를 이용한 해결법

 function RockBand(members) {
    var that = this; // 특정 변수에 this를 선언
    this.members = members;
    this.perform = function() {
      setTimeout(function(){
      // this라 선언한 that 사용
        that.members.forEach(function(member){ member.perform() })
      }, 1000)
    }
  }
  // setTimeout 스코프와 var that 스코프는 다르지만 자바스크립트의 클로저 특성으로 외부 변수 호출이 가능하다

  var theOralCigarettes = new RockBand([
    {
      name: 'takuya',
      perform: function() { console.log('a e u i a e u i')}
    }
  ])

  theOralCigarettes.perform()

bind를 이용한 해결법

  function RockBand(members) {
    var that = this;
    this.members = members;
    this.perform = function() {
      setTimeout(function(){
        this.members.forEach(function(member){ member.perform() })
      }.bind(this), 1000)
    }
  }

  var theOralCigarettes = new RockBand([
    {
      name: 'takuya',
      perform: function() { console.log('a e u i a e u i')}
    }
  ])

  theOralCigarettes.perform()

call, apply, bind 차이점

bind를 이용하면 함수를 실행할 때 함수 안에 있는 this가 bind로 갈아끼워진 this로 바뀐다.
call, apply는 함수를 실행하는 역할을 한다. (조금 더 자세히 알아볼 것)


  1. 5만 출력이 되는 이유는?

    전형적인 클로져 문제
    setTimeout이 실행되는 시점에는 루프가 이미 끝나있어서 i는 5가 들어가있어서 생기는 문제
    i를 var 대신 let을 쓰는 걸로 해결할 수 있음
    혹은 setTimeout을 IIFE로 감싸고, 파라메터로 i를 넘기는 것으로 해결 가능
const numbers = [1, 2, 3, 4, 5];
for(var i = 0; i < numbers.length; i++){ 
  (function(count){
    setTimeout(function(){
      console.log(`number index ${count}`);
    }, 1000);
  })(i)
}

let, const는 {} 블럭 스코프이다. 따라서 위 코드에서는 i가 length만큼 {}의 스코프가 따로 생성이 된다. (0 일때, 1 일때 ... 스코프가 따로따로 생성) setTimeout이 5번 실행이 될 때 i는 자신이 속해있는 중괄호 안에 있는 let을 참조한다.


  1. var, let, const의 차이
    var: function level scope를 가지며 이로 인해 호이스팅 현상이 일어난다. 재할당 가능
    let: block level scope를 가지며 재할당이 가능하다.
    const: block level scope를 가지며 재할당이 불가능하다. 그러나 할당된 객체의 함수를 이용해 객체를 변경하는 일은 가능하다.
const arr1 = []

arr1 = [1,2]; // Error!

// 가능
arr1.push(1);
arr1.push(2);
  1. 클로저란?
    자신의 scope 외부에 있는 것을 가져와 쓰는 것.
var a = 1;

function hello() {
  console.log(a); // a가 hello function scope에 없는데에도 접근 가능함.
}

클로저로 인한 메모리 누수?
https://itstory.tk/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%88%84%EC%88%98%EC%9D%98-4%EA%B0%80%EC%A7%80-%ED%98%95%ED%83%9C

실행 컨텍스트 : 실행되기 전에 컴파일러가 코드를 읽으면서 함수에 대한 정보를 갖고 있는 객체를 메모리에 스택 형식으로 쌓는다.
https://poiemaweb.com/js-execution-context

  1. undefined 와 null
    undefined는 빈값이지만 값이 할당되지 않았다의 의미이고,
    null도 빈값이지만 말 그대로 비어있는 '값'이다.

추천 도서

더글라스 크락포드의 자바스크립트 완벽 가이드
자바스크립트 패턴과 테스트

profile
블로그 이전했습니다

0개의 댓글