My Profile Photo

DongChanS's blog


수학과 학생의 개발일지


자바스크립트 (2) - Object, 브라우저 다루기

자바스크립트

  • 브라우저를 조작하기 위한 언어

  • HTML을 조작하기 위한 언어

DOM을 제대로 이해해야 브라우저를 통해 HTML을 조작할 수 있는지를 상세히 알 수 있다.

오늘 할 것

  • 변수, 배열, 오브젝트를 잘 활용해보기.

  • 브라우저 API를 활용해서 chromedino와 유사하게 만들기

    => 일단은 Margin을 활용해서 공룡이 뛰는 장면만 만들어보기.

1) 변수, 배열, 오브젝트 활용하기

2-1. ES6에서 변화된 함수문법

ES6 (= ECMAScript 6 = ECMAScript 2015 = Javascript Harmony)

이렇게 ES6 업데이트를 한 이후에는 자바스크립트가 개발자에게 편리한 기능들을 많이 추가했는데,

Arrow Function이라는 기능도 그 중에 하나이다.

이 기능은 => 를 이용해서 함수를 정의할 수 있게 한다.

  • 1단계

    let sum3 = (a, b) => {
        return a + b
    }
    
  • 2단계

    let sum3 = (a, b) => a + b;
    

    리턴이 한줄인 경우에는 이렇게 할 수 있다.

  • 3단계

    let sum4 = a => a + 2;
    

    변수 하나인 경우에는 괄호도 생략가능하다!

2-2. 배열을 순회하는 방법

배열을 순회하는 방법은 여러가지가 있다.

  • 첫번째

    let menu = ['짜장면', '짬뽕', "쌈밥", "김밥"]
    for (let i = 0; i < menu.length ; i ++ ){
        console.log(menu[i])
    }
    
  • 두번째

    For문을 이용하는 것 이외에도 리스트의 forEach메소드를 통해서 원소들을 전달할 수 있다.

    forEach(callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any): void

    A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.

    Performs the specified action for each element in an array.

    menu.forEach(function(food){
        console.log(food)
    })
    

    이것은 위에서 보았던 Arrow function을 통해 표현할 수도 있다.

    menu.forEach(food => console.log(food))
    

    forEach는 아무것도 리턴하지 않는다는 것을 유념해야한다!

  • 세번째

    map이라는 메서드를 이용할 수도 있다.

    map(callbackfn: (value: number, index: number, array: number[]) => any, thisArg?: any): any[]

    A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.

    Calls a defined callback function on each element of an array, and returns an array that contains the results.

    map메서드는 각 array의 원소들에 callbackfn을 적용해서 얻어진 리턴값을 새로운 array에 넣어주는 기능을 하기 때문에, 반드시 리턴값이 있어야한다!

    const numbers = [1,2,3,4,5,6];
    let squaredNumbers = numbers.map(function(num){
        return num*num;
    }) // [1, 4, 9, 16, 25, 36]
    
  • 그 외에도 Mozilla array에 array의 인스턴스와 메서드들을 볼 수 있다.

2-3. Type coercion

자바스크립트에는 파이썬의 input()과 비슷한 prompt()라는 함수가 있는데,

이것을 통해서 나이를 받아서 비교해보도록 하자.

const age = prompt("나이를 말해줘")
console.log(typeof(age)) // string

if (age > 30){
    alert("아재네")
} else if (age > 20) {
    alert("학식이네")
} else if (age > 8) {
    alert("급식이네")
} else {
    alert("아기네")
}

그런데 생각해보니, prompt라고 받은 인풋은 문자열인데 숫자랑 비교할 수 있다는게 이상하다!

왜냐하면 자바스크립트에는 type coercion 이라는 기능이 있기 때문이다.

강제로 age라는 문자열을 정수로 형변환을 해서 비교를 해준다.

이러한 형변환은 특히 ==로 두개의 값을 비교할 때 자주 나타난다.

const posts = [
    {id:1, title:"안녕"},
    {id:2, title:"자바스크립트"},
    {id:3, title:"브라우저 조작"},
]
posts.forEach(function(post) {
    if (post.id == "2"){
        console.log(post)
    }
}) // {id : 2, title : "자바스크립트"}

이 링크 에서 == 연산자가 어떻게 취급되는지 알 수 있는데,

2

false 와 “0”과 “” 이 같은등 이상한 경우가 많다

따라서 우리는 반드시 ===을 써야한다.

===은 두 객체의 타입까지 같아야만 true를 반환하기 때문에 엣지케이스들을 고려하지 않아도 되므로 편리하다.

3

2-4. 그밖의 Array의 메서드들

let users = [
    {id:1, username:'tony'},
    {id:2, username:'steve'},
    {id:3, username:'thor'},
    {id:4, username:'tony'},
]
  • array.find( function )

    array 원소들 e를 순서대로 보면서 function(e)가 True면 즉시 e를 반환하는 함수

    주의할 점은 함수 그 자체를 넣어야한다는 것이다!

    let tony = users.find(function(user){
        return user.username === 'tony'
    })
    
  • array.filter( function ) -> Array

    array 전체를 보면서 function(e)가 True인 원소들의 array를 반환하는 함수.

    let tonys = users.filter(function(user){
        return user.username === 'tony'
    })
    
  • reject : filter의 반대결과를 뽑아주는 함수(내장함수가 아니라고함..)

    • 직접 구현해보기

      let reject = function(array, func) {
          
          var res = []
          array.forEach( function(e) {
              if ( func(e) === false ) {
                  res.push(e)
              }  
          })
          return res
          
      }
      
    • filter를 사용해서 구현해보기

      let reject2 = function(array, func) {
          
          return array.filter(function(e) {
              return !func(e)
          }) // 함수 그 자체를 넘겨줘야하기 때문에 익명함수를 작성한다.
      }
      
  • array.every( function ) -> Boolean

    array의 원소들 e에 대해서 function(e)가 전부 true여야만 true를 반환함.

  • array.some( function ) -> Boolean

    array의 원소들 e에 대해서 function(e)중에서 하나라도 true이면 true를 반환함.

2) chromedino 뼈대를 만들기

완벽하게 구현하는건 아니고, 일단은 특정 명령(Event)을 수행할 때

4

이 둘리 이미지파일이 점프하는 것 처럼 보이게끔 하려고 한다.

<body>
    <div class="bg">
        <img src="madooly.png" id="dooly" width="100px" height="auto">
    </div>
    <script src="app.js"></script>
</body>

2-1. 어떤 Event에 반응하도록 만들기

  • addEventListener라는 녀석에게 이벤트를 추가하면 이벤트에 반응하도록 만들 수 있다.

    addEventListener(type: any, listener: (this: Element, ev: any) => any, options?: boolean AddEventListenerOptions): void

    Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options’s capture. When set to true, options’s capture prevents callback from being invoked when the event’s eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event’s eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event’s eventPhase attribute value is AT_TARGET. When set to true, options’s passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in §2.8 Observing event listeners. When set to true, options’s once indicates that the callback will only be invoked once after which the event listener will be removed. The event listener is appended to target’s event listener list and is not appended if it has the same type, callback, and capture.

    인자

    • 이벤트

      • 이벤트는 우리가 따로 정의하는게 아니라, 골라서 쓰면 된다.

        ( 이벤트 종류 )

        5

    • 함수 -> 그 이벤트가 발생했을 때 실행되는 함수

      • 함수의 인자는 이벤트 객체를 넣는데, 보통 e라고 정의한다.

        => 이 e를 이용해서 무언가를 할 수도 있긴하다!

    예시

    let dooly = document.querySelector('#dooly');
      
    dooly.addEventListener('click' , function(e){
        alert('호이')
        console.log(e)
    })
    

    이렇게 하면 둘리 이미지를 클릭할때 마다 alert창이 나오게 된다.

    이벤트를 출력해보면,

    6

    이런식으로 매우 많은 정보들이 있는데, 이런것들을 이용해서 나중에는 이벤트의 이벤트.. 식으로 엄청나게 많은 callback들을 만들어야한다고 한다.

  • 물론 이런 이벤트들은 다양한 종류가 있는데, 키보드를 누를 때에도 반응하도록 할 수 있다.

    (웹페이지에서 키보드를 눌러야 의미가 있으므로, document의 메서드로 쓰는게 맞다.)

    document.addEventListener('keydown', function(e){
        console.log(e.code)
    })
    

    7

    e는 여러 객체들이 있기 때문에 e.code라고 하면 어떤 키를 입력했는지를 출력할 수 있다

    => 이걸 이용해서 e.code의 값에 따라서 행동을 달리하면 될 것이다.

2-2. 둘리를 점프시키기

결론적으로 document에서 키보드 입력을 감지해서,

특정 키보드 입력일 때만, dooly에 먹혀있는 이미지태그의 style을 변화시키면 되는 것이다.

이를 위해서 dooly.style을 조절하면 된다.

document.addEventListener('keydown', function(e){
    if (e.code == "ArrowUp") {
        dooly.style.marginBottom = "100px";
    } 
})

그런데 문제는 “a” 라는 키를 입력했는데, 이건 영어권 키보드에는 “a”겠지만 다른 나라에서는 똑같은 위치지만 다른 언어로 인식될 수 있다

따라서 e.code보다는 키보드 자판 위치에 따른 유니크한 id를 가지고 있는데 e.keycode로 할 수 있다.

http://keycode.info/ 에서 보면, ArrowUp은 38과 대응되기 때문에 이런식으로도 코드를 짤 수 있을 것이다.

8

document.addEventListener('keydown', function(e){
    if (e.keyCode == 38) {
        dooly.style.marginBottom = "100px";
    } 
})

더 생동감있게 뛰려면 CSS Transition을 알고 있어야 한다는데..

comments powered by Disqus