JavaScript

람뽀·2024년 3월 29일

OZ 코딩스쿨

목록 보기
4/11

2024.3.29

~2024.5.24

3.29 자바스크립트 수업이 시작되었다. 기본적인 개념부터 강의가 진행되는데 역시 객체..변수..함수..뭔가 단어만 들어서는 확 와닿지 않는 느낌이다. 그러나 독학할 때 혼자서 잘 이해가 안된다고 일단 넘어갔다가 뒤에서 또 햇갈렸던 경우가 많아서 이번에는 물어볼 기회도 사람도 있으니 자세하게 보면서 진행할 예정이다.
4.1 지난 주 금요일 라이브세션, 강사님께서 flex와 grid 공부하고 활용해보신분 있냐는 물어보셨는데 대답을 할 수가 없었다. 나는 공부한내용을 이해하고 과제는 했는데 스스로 무언가를 만들어 볼 생각은 안했다. 그래서 아 그냥 내가 복습을 제대로 안했구나 하고 넘어갔는데, 그 다음날 밤 누워서 갑자기 깨달음을 얻었다. 아 내가 문과식으로 외우고 정리하는 공부 안하겠다고 다짐해놓고 또 블로그랑 노션에 정리만하고, 그것을 활용해서 공부하는건 안했구나.. 앞으로는 가볍게 정리 후 실습해보는 시간을 가져야겠다.


javascript 개념

  • 자바스크립트는 웹 페이지에서 복잡한 기능을 구현할 수 있는 스크립팅 또는 프로그래밍 언어이다. 동적으로 변경되는 콘텐츠를 만들고, 멀티미디어를 제어하고, 이미지에 애니메이션을 적용하는 등 거의 모든 작업을 수행 할 수 있다.
    서버개발, 어플개발 등 다양한 목적을 위해 사용할 수 있지만 주된 활동 분야는 웹개발이다.

  • 프로그래밍 언어

    • 프로그래밍 : 프로그래밍이란 컴퓨터에게 실행을 요구하는 일종의 커뮤니케이션으로 0과 1만 이해할 수 있는 기계가 실행할 수 있을 정도로 정확하고 상세하게 요구사항을 기계에게 설명하는 작업이다.
    • 프로그래밍 언어 : 컴퓨터 시스템을 구동시키는 소프트웨어를 작성하기 위한 형식의 언어로 기계의 언어와 인간의 언어는 체계가 다르기 때문에 컴파일러 혹은 인터프리터를 사용해야 한다. 즉 프로그래밍 언어는 사람과 컴퓨터(인터프리터나 컴파일러)가 모두 이해 할 수 있도록 만들어진 인공언어이다.
    • 인터프리터 : 코드가 위에서 아래로 실행되며 줄 단위로 번역되어 코드 실행 결과가 즉시 반환된다. 브라우저에서 코드를 실행하기 전에 코드를 다른 형태로 반환할 필요가 없기 때문에 번역 과정이 비교적 간단하며 코드는 프로그래머에게 친숙한 텍스트 형식으로 수신되어 바로 처리된다. 그러나 실행할 때 마다 매번 기계어로 번역하는 과정을 재수행한다. ex) js, python, sql
    • 컴파일러 : 컴파일러를 사용하는 컴파일 언어는 컴퓨터에서 실행되기 전에 다른 형태로 컴파일 된다. 예를들어 C/C++은 코드를 컴파일러로 기계연어로 변환하여 그 결과를 컴퓨터가 실행한다. 컴파일러는 전체 프로그램 코드를 스캔하고 그 코드 전체의 목적코드를 한번에 변환시킨다. 그래서 코드를 재실행할 때마다 빠른시간 내에 전체 실행이 가능한 장점이 있지만 일부를 수정하는 경우에도 전체 프로그램을 다시 컴파일 한다는 단점이 있다. ex) C/C++, C#
  • 자바스크립트는 인터프리터를 사용하는 가벼운 프로그래밍 언어이다.
    웹 브라우저는 자바스크립트 코드를 원문 텍스트 형식으로 입력받아 실행하는데, 대부분의 모던 자바스크립트 인터프리터들은 실제 성능 향상을 위해 JIT컴파일(just-in-time)이라는 기술을 사용한다.
    JIT 컴파일은 스크립트의 실행과 동시에 소스코드를 더 빠르게 실행할 수 있는 이진 형태로 변환하여 최대한 높은 실행속도를 얻는 방법이다. 변환이 되는데 컴파일이 아니냐? 할수 있지만, 컴파일이 미리 되는것이 아니라 런타임에 처리되기 때문에 js는 아직 인터프리터 언어로 분류된다.

DOM : Document Object Model.

  • 문서를 객체의 형태로 정리한것. 브라우저가 화면을 그리려면, 파일을 해석하는 과정을 거쳐 화면을 통해 결과를 보여주는 렌더링 작업이 필요하다. 그래서 브라우저의 렌더링 엔진이 서버로부터 받은 파일을 브라우저가 이해 할 수 있는 구조로 재구성하여 메모리에 저장하는 작업을 한다. 이 과정에서 만들어지는것이 DOM, CSSOM이고 이러한 과정을 파싱이라고 한다.(즉 브라우저가 우리의 파일을 이해하고 활용할 수 있도록 하기 위해서 만들어지는 것이다.)
    ( HTML은 DOM / CSS는 CSSOM으로 변환 )
    제일 바깥에 있는 html부터 head, body와 그 안에 포함된 시멘틱태그 또 그 안에 포함된 div, span 등을 구조화 하다보면 나무와 같은 형태가 나오게 되고 이것을 DOM tree라고 한다. 이렇게 브라우저는 파일을 객체로 표현 할 수 있는데 javascript는 객체를 제어 할 수 있도록 만들어져 있기 때문에 html과 css를 제어하여 이벤트를 발생 시킬 수 있는 것이다!!@@@@!!@# (이런식으로 생각해본적 없는데 넘신기. 사실은 이게 첫 단계였던거징) 이렇게 문서화된 객체의 최상위에 위치한 노드(DOM에서 각 요소를 나타내는 기본 단위, 모든 개개의 객체(html, body, div, p 등등 모든 태그도 속함))가 document객체이기 때문에, 우리가 javascript에서 html이나 css에 접근할때 첫 명령어로 document를 입력 하는 것이다. 즉 DOM이 생성되면 DOM트리 내의 노드(div나 p등)와 그 노드의 속성(id, class)을 활용하는 메소드를 통해 문서를 조작 할 수 있다.
    예시1) document.queryselector('li.list') 메소드는 선택자를 인자로 받아 전달받은 선택자와 일치하는 문서내 첫번째 요소를 반환한다. 일치하는 요소가 없으면 null을 반환한다. (즉 예시에서 li.list에 해당하는 값이 많아도 첫번째자식만을 반환한다)
    예시2) document.queryselector('li.list').textContent는 해당 객체(요소, 위에서 html을 객체로 만들었다고 했으니 우리가 사용한 태그들도 다 객체화 되어있고, 그 안의 값들도 객체의 프로퍼티로 적용되어 있어서 객체의 형태로 뽑아내고 사용 할 수 있다)가 포함하고 있는 텍스트 콘텐츠를 표현하는 속성이다. 요소가 포함한 텍스트를 읽을 수도, 수정할 수도 있다. 예시1은 메소드라서 괄호안에 어떤 값이 들어가고 예시2는 프로퍼티라서 괄호없음
    +) 이렇게 수정하거나 추가한 객체들에게도 css를 미리 지정해놓으면 의도한대로 스타일을 지정 할 수 있다.

  • 자바스크립트는 웹브라우저 및 하위객체가 가진 기능을 구동하거나 HTML/CSS를 통해 렌더링된 화면을 조작하는 역할을 한다. 이와 같은 역할을 정상적으로 수행하기 위해서는 코드를 올바른 위치에 작성하는것이 중요하다.

    • HTML내부에 직접 작성하는 방법 / 외부의 js파일을 만들고 html에 연결하는 방법이 있다.
          <!doctype html>
      <html lang="ko">
        <head>
          <meta charset="UTF-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <title>자바스크립트 소개</title>
          <style></style>
        </head>
        <body>
          <script src="02-자바크스립트소개.js">
            // html 내의 js 코드
            alert();
          </script>
        </body>
      </html>
      외부 파일과 연결하는 방식에서, CSS를 연결했던 link와의 차이점이라면 <link>는 head태그에 썼던것과 다르게 js는 body태그 안에 적는다. 웹 컨텐츠를 js가 동작시킬 때 파일을 다 읽고 난 후에야 동작을 입힐 수 있기 때문에 인터프리터언어인 js의 특징상 코드가 아래쪽에 배치되어야 하기 때문이다.
      +) 모던자바스크립트에 해당 부분이 나옴 : 자바스크립트를 처리할때는 브라우저의 렌더링엔진이 아니라 자바스크립트 엔진이 처리하도록 되어있는데 이 과정이 비동기적으로 진행되기 때문에 만약 html 코드가 진행되는 중간에 script코드를 만나면 제어권한을 스크립트 엔진으로 넘기게 된다. script파일의 로드와 파싱이 완료되면 다시 브라우저 엔진으로 넘어가서 이전에 멈췄던 DOM생성을 재개하는 방식으로 진행되기 때문에 HTML요소의 로딩지연이 생길 수 있고 DOM이 완성되지 않은 상태에서 js가 DOM을 조작하려하는 에러가 발생 할 수도 있다.
  • 자바스크립트가 명령을 내리는 소프트웨어적 대상이란 웹브라우저, 웹요소, 웹스타일 등을 의미한다.
    명령을 대상에게 내리면 입력->처리->출력의 단계를 거친다. (여기서 출력이란 화면에 보여주는 것 외에도 데이터를 보내주거나 프로그램의 상태를 변환하는 다양한 일을 포함한다.)

  • 이 때 자바스크립트 명령문으로 어떤 처리를 지시하고자 하는 대상을 가리켜 '객체'라고한다. 대부분의 다양한 객체 명령문은 미리 정의되어 있어서 사용자는 사용법을 알고 있으면 된다. ( 객체마다 명령을 내리는 명령문이 무엇인지 알면 된다는 의미로 받아들였다. 예를들어, 콘솔디버그에 화면을 띄우는 명령을 하고싶으면, 콘솔객체의명령문 console.log()를 사용하는 것이다. 이런식으로 자바스크립트에는 객체(처리하고자하는대상)에 대한 정보가 미리 모두 들어가 있는 것이다. 우리는 거기서 자주 사용되는 방법을 하나씩 빌려와 사용하는 것 뿐!)

  • 자바스크립트는 객체 기반의 프로그래밍 언어로 js를 구성하는 거의 모든것이 객체이다.

    • 객체 : 객체는 0개 이상의 프로퍼티로 구성된 집합이다.
    • 프로퍼티 : 프로퍼티는 key:value로 구성되어있다.
    let person = {
       name: 'Lee', // name => 프로퍼티 키, 'Lee' => 프로퍼티 값
       age : 20   // age => 프로퍼티 키 , 20 => 프로퍼티 값
    }

    위 코드가 객체의 형태이다. 객체의 프로퍼티 값으로는 함수가 들어 갈 수도 있고 이 경우에는 메서드 라고 한다.
    즉, 객체는 프로퍼티와 메서드로 구성된 집합체이다. 프로퍼티는 객체의 상태를 나타내고, 메소드는 프로퍼티를 참조하여 조작하는 동작인 것이다.

    • 객체에 접근하는 방법 : 마침표 표기법 / 대괄호 표기법

      변수명.a;    // 마침표 표기법   
      변수명['a']; // 대괄호 표기법
      
      let person = {
       name: 'Lee',  //프로퍼티를 나열할 때는 쉼표(,)로 구분합니다.  
       age : 20    
      };
      
      //마침표 표기법에 의한 프로퍼티 접근
      console.log(person.name); //Lee
      
      //대괄호 표기법에 의한 프로퍼티 접근
      console.log(person['name']);  // 실행결과: Lee

여기서 들었던 생각!@
평소에 사용하던 console.log()가 마침표 표기법으로 console이라는 객체에 접근한 방법이라면 대괄호 표기법도 가능한걸까?
console["log"]("Hello, world!");
놀랍게도 됐따!@!@!@ 너무신기해
늘 객체..console..뭐 뭔지 잘 모르겠지만 그냥 콘솔창에 띄워주는거구나 하고 막연하게 썼었는데 결국 모두 내 컴퓨터에 저장되어있는 객체일 뿐이었구나 하고 이해가 되었다. console.log를 포함한 window.alert() 등도 어딘가에 모두 저장되어있는 객체였던거구나!@
GTP에 검색해보니 점표기법이 접근성이 좋아 많이 사용하지만 변수를 사용하여 동적으로 접근할 때는 대괄호표기법이 더 좋다고 한다.

  • js의 주석을 처리하는 방법은 html, css에서 썻던 것 둘 다 쓸수있다.
    // or /**/
  • 아까부터 주구장창 이야기한 console은 자바스크립트 코드를 점검할 수 있는 시스템으로, 브라우저에 내장된 하위 객체라서 브라우저의 객체로도 접근 할 수 있다. 브라우저에서 개발자 도구를 열면 메뉴 중 콘솔이 존재한다. 이것이 디버깅 콘솔로 코드를 테스트 할 수 있다.
    console도 객체이기 때문에 명령을 내릴 수 있다. console.log('x')는 디버깅콘솔에게 콘솔창에 x라는 문자를 띄워줘 라는 뜻이다. x의 자리에는 사용자가 원하는 내용을 입력하면 되지만, 자바스크립트의 문법으로 표현할 수 있는 데이터만 사용할 수 있다. 이렇게 js로 표현가능한 데이터의 형식을 자료형(datatype)이라고 한다.

자료형

  • 기본(원시)자료형 : 숫자, 문자열, 불리언boolean(true or false), undefined(변수에 값이 담긴적이 없음을 의미. 변수를 선언하고 값을 할당하지 않으면 undefined가 자동으로 할당되는데 이것은 undfined로 초기화 된 것.), null(변수에 값을 의도적으로 담지 않았음을 의미. undefined의 typeof는 undefined인데 null의 type은 object이다. 오랜 js의 버그), symbol(이름의 충돌 위험이 없는 유일한 객체의 프로퍼티를 만들기 위해 사용함. 심볼 함수를 호출해서 생성. 유일한 객체식별자이자 for...in과 같은 열거 프로퍼티를 무시함을 이용하여 사용할 수 있음(의도적으로 값을 숨기는데 사용할 수 있음))
    js에서 원시자료형은 변경될 수 없는 값을 의미함. 문자형을 예시로 들면,
    위 코드에서 첫번째 구문이 실행되면 식별자 str은 "Hello"문자열이 생성되고 메모리에 할당이 됨. 식별자 str은 해당문자열의 메모리 주소를 가지고 있다가 두번째 구문이 실행되면 기존 메모리에 담겨있던 "Hello"를 수정하는게 아니라 새로운 문자열 "world"를 새로운 메모리에 할당하고 식별자str은 새로운문자열에 대한 주소를 가지고 있게 되는것임. 이런식으로 문자열과 같은 원시자료형은 한번 생성되면 모두 메모리에 존재하고 있음. 여기에 더해서 문자열의 경우는 유사배열이라 인덱스를 통해서 접근할 수 있음. str[0] 하면 "H"가 반환됨. 그러나 str[0]='J'처럼 재할당을 해도 "Hello"는 바뀌지 않음. 만약에 문자열 뒤에 새로운 문자열을 추가한다해도 기존의 Hello를 수정하는게 아니라 새로운 문자열의 메모리를 할당할것임.

  • 참조자료형 : 객체, 배열, 함수 등 기본자료형을 제외한 모든 것으로 여러개의 데이터를 한번에 다룰 수 있는 자료형이다. 원시자료형과 다르게 가변하는 복잡한 데이터를 담고 있으며 값이 직접 저장되는게 아니라 저장된 값에 접근하는 메모리 주소를 참조하기 때문에 참조자료형이다.
    예를 들어 위와같이 배열2에 배열1을 할당하면 [1,2,3]배열에 접근하는 주소를 나눠준것일 뿐 배열 자체를 저장해준것이 아니기 때문에 배열1만 수정해도 배열2까지 바뀌게 된다.하나의 배열을 두개의 변수가 함께 참조하고 있기 때문에 하나의 변수만 수정해도 두개의 배열이 같이 바뀌는 것처럼 보인다.

이러한 자료형은 단순히 표시하는것을 넘어서 연산을 할 수도 있다.

  • 연산가능 : 더하기+ / 빼기- / 곱하기* / 나누기/ / 나머지%
  • typeof 연산자는 피연산자의 자료형을 나타내는 문자열을 반환한다.
    typeof '문자열' // 'string'
    typeof 3 // 'number'
  • 문자열 : 어렵게 표현하자면 문자, 숫자, 특수문자 등 다양한 기호를 조합해 만들 수 있는 기호의 집합. 따옴표(작은따옴표 가능)로 시작해 따옴표로 끝나는 데이터이다. ( 따옴표는 화면상 출력되지 않음 )
    문자열을 표현할 때 'asdf"이런식으로 짝을 짓지 않아서는 안되고, 따옴표를 문자열 안에서 표현하고 싶을때는 'as"d"f'이런식으로 외곽에서 사용한 따옴표와 다른 종류를 사용해야한다. 그런데 웹브라우저에서는 문자열의 내용을 의도와 다르게 해석할 때가 있는데, 이때 escape문자 \(역슬래시)를 사용하면 된다.
    console.log("안녕하세요 \"홍길동\" 입니다.")//안녕하세요 "홍길동" 입니다.`
    위 코드는 역슬래쉬를 넣지 않았다면 오류가 발생했을 것이지만 역슬래쉬를 넣음으로서 원하는 결과를 얻을 수 있다.
    (escape 문자 : \n 줄바꿈, \t 수평탭, \\역슬래시
    • window.prompt('x') : 문자열을 활용하는 메소드로 사용자로부터 문자열을 입력받을 수 있는 다이얼로그 박스를 열어준다. x부분에는 다이얼로그박스에 띄울 메세지를 전달할 수 있다.
      화면에 출력된 다이얼로그박스는 커서를 깜빡이면서 입력을 유도한다. 실행시 사용자로부터 문자열을 입력받고, 자신이 사용된곳에 그대로 반환한다. 즉 메소드가 문자열로 바뀌게 된다. (문자열이 아닌 숫자 등 데이터형이면 다 받을 수 있다.) 취소를 누르면 null이 반환된다.
    • 문자열을 표현하는 방법은 '', "" 외에도 ``백틱을 사용한 템플릿 리터럴이 있다. 템플릿리터럴은 반환값이 존재하는 코드, 즉 표현식을 내장할 수 있다. 이는 문자열의 내용에 데이터를 삽입하는것이 가능하다는 의미로 템플릿리터럴로 표현한 문자열 내부에 플레이스홀더${}를 기입하고 그 안에 데이터를 기입하면 데이터는 문자열의 멤버가된다. (문자열이된다) 이렇게 템플릿리터럴을 이용하여 데이터를 삽입하고 그것과 함께 문자열을 완성하는것을 문자열 포맷팅(어떤 양식을 만들어서 내용을 삽입하는것)이라고 한다. 또 일반적인 문자열의 경우 줄바꿈을 인식하지 못해서 \n을 사용해야 하는데 템플릿 리터럴을 사용한 경우에는 엔터를 여러줄하면 그대로 입력된다.

여기서 햇갈렸던 점. const는 상수라서 한번 값을 정하면 수정 못하는거 아닌가? 그런데 위에서 prompt는 데이터를 입력 받을 때 마다 값이 수정되는데 왜 오류가 안나지? 하는거였다. 이것은 내가 상수를 단어 그대로만 이해하고 프로그램적으로 이해하지 못했기 때문이었다. const는 선언과 동시에 초기화가 이루어지고 재할당을 할 수 없다는 의미의 변수선언키워드이다. 위 코드의 경우 재할당이 이뤄지는게 아니라 선언과 동시에 초기화가 이뤄지고 있는 것이고, const는 초기화의 단계에서는 얼마든지 값이 수정될 수 있기 때문에 오류가 나지 않는 것이다.

  • undefined : js가 빈상태로 변수를 두지않고 undefined로 초기화 하기 때문에 선언이후 값을 할당하지 않은 변수는 undefined를 값으로 가지게 됨. 즉, undefined가 결과값으로 나온다면 값이 할당된적이 없다는것을 간파할 수 있음으로 의도적으로 값을 비워뒀을 경우에는 null을 쓰는것이 권장됨(잠깐 값을 비워두는것이 아니라, 예를들어 어떤 물건의 값을 정하는데 이 물건의 값을 정할 생각이 없기때문에 비워두는경우에는 null로 채워주는것이 맞음)

  • null : NULL, Null과는 다름. js는 대소문자를 구별하기 때문. 의도적으로 변수에 값이 없다는것을 명시한다는 것은 변수가 기억하는 메모리 주소의 참조정보를 제거하라는 뜻임. js엔진은 누구도 참조하지 않는 메모리영역은 가비지컬렉션을 수행함. (가비지컬렉션..이라는게 대충 찾아봤을때는 더이상 사용하지 않는 메모리를 해제하는 프로세스를 말하는데 메모리 누수로 이어질 수 있기 때문임. 그런데 코드상에 존재하는데 어떻게 메모리를 해제한다는거지..? 추가공부필요)

  • 배열 Array : 여러개의 데이터를 순서대로 담는 자료형
    배열에 담긴 데이터 하나하나를 요소Element라고 부르며, 0부터 시작하는 인덱스를 값 마다 하나씩 가진다.

    • 배열의 요소를 확인하는 방법은 arr[x] 로 대괄호에 인덱스를 넣어서 해당 인덱스에 어떤 요소가 있는지 확인 할 수 있다. 위 이미지에서 과일[0]은 사과이다. 할당연산자를 이용하여 과일[0]=체리 라고하면 사과대신에 체리를 할당할 수 있고, 과일[6]=포도 처럼 없는 인덱스를 입력하면 그자리에 새로 추가된다. ( 그럼 만약에 마지막 인덱스는5인데 인덱스10에 추가하면? 그 사이에 빈 인덱스에는 undefind가 할당됨 )
    • 배열의 길이 확인 : 배열.length
    • 배열 메서드를 이용하여 요소를 추가/제거 하는 방법
    • 요소의 앞에 추가/삭제 : unshift / shift
    • 요소의 뒤에 추가/삭제 : push / pop
  • 객체 : 위에서 객체는 좀 어렵게 설명했는데, 자료형으로서 설명하면 여러개의 데이터에 이름을 붙여 저장하는 자료형이다.
    • { 키 : 값 } 의 형태를 속성 property라고 한다. (html의 속성 attribute와 다르다)
    • 위에서 적었던대로 마침표표기법, 대괄호표기법 객체.키, 객체["키"]로 객체의 데이터를 확인 할 수 있다. 존재하지 않는 값에 접근하면 undefined가 확인된다.
    • 배열과 마찬가지로 할당연산자를 사용하여 데이터를 할당 할 수 있다.(재할당 할 수도 있고 추가 할 수도 있다)
    • 객체를 삭제하는 방법 : delete 객체[키]
  • boolean : 참true / false 거짓. 모두 소문자로 써야함.
    • window.confirm('x') : 사용자에게 확인과 취소 둘 중 하나를 선택하게 하고, 선택에 따라 true나 false를 반환함.

변수와 상수 그리고 대입

  • 변수variavle : 프로그래밍 언어에서 데이터를 관리하기 위한 핵심 개념으로 js에서는 값이 변하는 데이터를 저장하고 관리하기 위한 공간으로 변수를 사용한다. 변수를 사용하여 데이터를 저장하면 재사용에 용이하다.

    let 변수명 = 데이터;
    let 변수명;
    변수명 = 데이타; 
    • 변수명: 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름. 변수명에는 오로지 문자, 숫자, 기호($, _만 가능)만 포함 될 수 있으며 첫 글자로 숫자는 올 수 없다.또한 이미 다른 뜻을 가지고 있는 단어는 변수명으로 사용 할 수 없다.(객체명이나 문법키워드)

    • 변수 값: 변수에 저장된 값

    • 선언 : 변수를 만드는 작업

    • 초기화 : 만들어진 변수에 첫 데이터를 지정하는 작업.
      (선언과 초기화는 동시에 이루어지지 않을 수도 있다. 일단 변수명을 선언만 해두고 값은 나중에 초기화 해도 된다.)

    • 할당 : 선언된 변수에 값을 저장하는 것
      (GPT 피셜 할당에 초기화가 포함 될 수 있다)

    • 참조 : 변수에 저장된 값을 읽어 들이는 것

    • 할당 연산자 : 수학에서의 같다는 의미가 아니라 변수에 데이터를 할당했다는 뜻이다. (앞으로 객체나 배열에서도 = 이 나오면 객체나 배열에 값을 할당하겠다 라는 뜻이다.)

      • java나 c, kotlin등은 정해진 데이터만 정해진 변수에 담을 수 있지만 js의 변수에는 데이터의 형태를 구분하지 않고 할당 할 수 있다. typescript는 이러한 점을 보완했다.
    • 대입 연산자 : 오른쪽 피연산자의 데이터를 왼쪽 피연산자에 집어넣는 작업으로 대입연산자를 산술연산자와 함께 사용하면 오른쪽값을 왼쪽에 산술해서 넣겠다는 뜻이다!

    • 변수 이름은 변수에 저장된 값의 의미를 파악할 수 있도록 명확한 네이밍을 해야 한다. 이는 협업 시 코드를 이해하기 쉽게 만드는데 도움을 준다.
      변수를 지정하면 데이터를 필요할 때마다 재사용 할 수 있다. 데이터를 기억하기 위해 사용하는 변수는 한번에 하나의 데이터만 기억 할 수 있다.

      	let 변수명 = 데이터1;
         변수명 = 데이터2;
         변수명 = 데이터3;

      이와 같이 여러번 입력했어도 최종적으로는 데이터3만 기억된다.(재할당가능)!

    • 변수 선언에 필요한 키워드로 var, let, const가 있다. ( 요즘은 var는 잘 쓰지 않는다. 이것은 뒤에 적을 예정 )

      • let : 변수명 중복 불가능, 변수 값 재할당 가능, 호이스팅 되지 않음, 스코프의 범위가 블록스코프.

      그럼 호이스팅과 스코프가 뭔데!?

    • hoisting : JavaScript 호이스팅은 인터프리터(프로그래밍 언어의 소스 코드를 바로 실행하는 컴퓨터 프로그램 또는 환경)가 코드를 실행하기 전에 함수, 변수, 클래스 또는 임포트(import)의 선언문을 해당 범위의 맨 위로 끌어올리는 것처럼 보이는 현상을 뜻함. 그래서 호이스팅이 되는 var를 예로 들면

      console.log(num);
      var num=10; // 실행결과 undefined

      실행 결과가 이상하게 나온다. 인터프리터 언어인 js는 위에서 아래로 읽어 들이기 때문에 선언보다 먼저 나온 명령에서 오류가 떠야하는데 undefined가 출력되는 것이다.
      호이스팅을 잘 알려면 선언 / 초기화 / 할당의 단계에 대해 잘 파악하고 있어야 한다.
      선언은 let number와 같이 키워드+변수명을 선언만 해둔 단계를 말하고, 초기화는 선언한 후에 아무것도 값을 할당하지 않았을때 js가 undefined를 첫 값으로 넣어주는 것을 말하고, 할당은 let number = 10과 같이 실제로 값을 넣어준 단계를 말한다. let과 consts, 함수 표현식과 화살표함수는 선언단계에서 호이스팅이 되기 때문에

      console.log(x)   // <-TDZ
      let x = 'hello'
      // cannot access 'x' before initialization

      다음과 같이 초기화 전에는 접근할 수 없다 라는 오류코드가 뜬다. 즉 선언만 되어있다는 뜻이다. 선언도 하지 않으면 not defined = 정의되지 않았다 라고 뜬다. 여기서 위 코드의 제일 첫줄 = 선언만 된 상태의 변수는 TDZ = temporal dead zone 일시적 사각지대에 있다고 표현한다. 선언과 초기화의 사이에서 값을 확인할 수 없는 단계이다. TDZ가 있기 때문에 const와 let은 var처럼 undefined로 초기회되지 않고 오류코드가 뜨는것이다.(아래에 쓰겠지만 var는 호이스팅방식과 스코프범위 때문에 최근 js에서는 사용하지 않는다. 아마 var의 허점을 방지하기 위해 만들어진 방식이 아닐까 생각했다)
      let, const, 함수표현식, 화살표 함수가 선언단계에서 호이스팅 되는건 어떻게 보면 당연하다! 선언을 했으니까! 선언을 해놨으니까 선언단계에서 호이스팅이 된다!
      아까 공부한 var는 초기화까지 마치고 호이스팅 되도록 동작하기 때문에 선언 이전에 참조를 해도 undefined라는 값을 반환한다.
      함수 선언식은 할당까지 모두 마친 후에 호이스팅 된다. 그래서 만든 후 윗레벨에서 코드를 작성해도 이상없이 함수가 실행되고 값을 참조 할 수 있다.

    • scope : 스코프란 현재 실행되는 컨텍스트를 말하고, 컨텍스트는 현재 값과 표현식이 해당 범위 안에서 표현되거나 참조 될 수 있음을 의미한다. ( 좀 쉽게 설명해서 내가 어떤 변수를 어떤 범위 안에서 선언하면, 그 변수는 해당범위를 벗어나면 사용 할 수 없다. ) var는 함수스코프를 사용한다. 함수 내에서 선언된 변수라면 함수 내의 어디서든 사용 할 수 있다는 뜻이다.

    • hoisting이 된다는 것은 코드가 내 의도와 다르게 동작 할 수 있다는 것을 의미하며, 함수스코프라는 것은 블록스코프에 비해 범위가 넓어서 명확하게 명령을 내리기 힘들다는 것을 의미한다. 여기에 더해서 var는 변수명을 중복 할 수 있어 오류를 발생시킬 확률이 높다. 그래서 최근에는 var의 사용을 지양하고 있다.

  • 상수 : 수식에서 변하지 않는 값을 뜻하며, 변수와 반대된다. 단 하나의 데이터만을 위해 사용하는 이름으로 한번 정의하면 값의 변경이 불가능하다. 그 외에 변수명을 짓는 방법, 선언, 할당, 초기화 등은 동일하다.

    • const : 변수명 중복 불가능, 변수 값 재할당 불가능, 호이스팅 되지 않음, 블록스코프 범위. 변수 값 재할당이 불가능 하기 때문에 선언과 동시에 초기화를 해야한다.

네이밍컨벤션

  • 코드의 가독성과 유지보수성을 높이기 위한 코드 작성 규칙으로 협업과정에서 다른 개발자가 코드를 이해하기 쉽게 만들고, 프로젝트 전반적인 품질을 향상시키기 위해 일관된 네이밍 규칙을 따르는 것을 말한다.
    • 카멜케이스 camelCase : js의 변수, 객체의 속성, 함수는 모두 카멜케이스를 사용한다. 첫번째 단어는 소문자로 시작하고 이후 각 단어를 대문자로 시작한 형태가 낙타의 등과 비슷하다.
      ex : myVariable, claculateTotalWidth
    • 파스칼케이스 Pascalcase : 모든 단어의 시작을 대문자로 시작한다. 클래스와 생성자를 사용할때만 제한적으로 사용된다.
      ex : Product, UserProFile
    • 스네이크케이스 snake_case : 단어와 단어사이를 언더스코프로 구분한다. js에서 거의 사용되지 않는다. 모든 단어는 소문자이다
      ex : my_variable, calculate_total_width
    • 대문자스네이크케이스 UPPERCASE_SNAKE_CASE : 모든 단어 대문자, 단어와 단어사이 언더스코프, 상수를 선언할 때 사용
      ex : MAX_HEIGHT, DEFAULT_COLOR
    • 케밥케이스 kebob-case : js에서는 일반적으로 사용하지 않고, html, css에서 class나 id를 명령 할 떄 사용함
      ex : my-variable, calcuate-total-width
    • 이 외에도 의미 있는 이름을 사용하고, 짧고 간결하게 사용하는것이 중요하며 boolean변수를 명령 할 때에는 is, has, can, should 등의 접두사를 사용하여 명령한다.
      ex : isVisible, hasChildren

여기서 햇갈렸던것!@
html, css할때 분명히 언더바고 그냥바고 막 썻던것 같은데 모지..? 해서 생각해보니까 위에서 말한거는 js의 경우에 막 사용하지 말라고 했던거지 케밥케이스를 보면 html, css에서 사용한다고 되어있더라!

DOM 메소드와 속성

  • DOM : 웹페이지에 표시되는 다양한 요소들을 프로그래밍적으로 다룰 수 있도록 해주는 인터페이스. 처음에는 주로 요소를 선택하고 선택한 객체의 값을 확인하는 것들을 먼저 배웠다

메소드

  • document.querySelector('접두사+x') : 접두사는 . or #. 괄호안에 들어간 css선택자에 해당하는 태그의 첫 번째 요소를 선택함.
  • document.querySelectorAll('접두사+x') : css선택자에 해당하는 모든 요소를 선택함.
  • document.getElemetById('x') : 접두사 필요없음. Id를 선택하는것이라고 명시되어 있기 때문임. id속성값을 기반으로 해당하는 요소를 선택함.
  • document.getElementsByClassName('x') : 접두사 필요없음. class속성의 값을 기반으로 여러 요소를 선택함.
  • document.write('x') : 문서(Dom)에 컨텐츠(html코드) x를 추가한다. 아래코드는 입력값을 받고 그 값이 보람과 같으면 화면에 해당 텍스트를 추가한다. dom에 코드를 추가하는 것이기때문에 내부에 <br>등의 태그를 입력하면 텍스트형태로 입력되는것이 아니라 태그의 형태로 입력되어 적용이 됨.(다음줄로 가짐)
    let name = prompt('이름이 무엇이요?');
    document.write('보람' === name);
    (querySelectAll이랑 getElementsByClassName의 차이가 뭐지?해결!)
  • document.createElement('tag') : 지정된 이름의 html요소를 만들어 반환한다. ( 만들어 낼뿐 위치를 dom트리 내부에 위치를 지정해주지 않으면 화면에 나타나지 않는다! 그래서 append()와 함께 자주 쓰인다)
  • Element(부모요소).append(자식요소) / appendChild(자식요소) : dom 내의 부모요소에 자식요소를 포함시킨다. append는 태그 외에도 숫자나 문자열 등을 추가하거나 한번에 여러개의 노드객체를 추가 할 수도 있지만 반환값이 없고, appendChild는 오직 하나의 노드객체만 추가 할 수 있지만 반환값이 있다. (녹화영상 강사님은 후자를 더 많이 사용한다고 하셨고, 라이브세션 강사님은 전자를 더 많이 사용한다고 하셨는데 아무래도 현직에서는 다양한 값을 추가해야 하는 경우가 더 많아서 그런것같고, 교육적인 관점으로는 appendChild가 더 범위가 좁고(항상 js공부할때 보면 오류의 가능성을 줄이기 위해서 이용범위가 더 좁은걸 쓰라고 하더라)반환값이 있어서 재사용하기 좋기 때문에 주로 사용하는게 좋다고 하시는 것 같다)
  • Element.prepend (추가할 요소) : append는 부모요소중에 제일 뒤에 추가하는거고, prepend는 자식요소 중에 제일 앞에 위치 시킨다.
  • Element.insertBefere (추가할 요소, 뒤에 올 요소) : 자식요소중 중간에 위치시킬 때 쓴다. 추가할 요소와 그 요소의 뒤에 올 요소를 값으로 넣어준다.
  • Element.setAttribute(속성이름, 속성값) : 요소에 속성을 수정하거나 추가하는 메소드이다.
  • Element.remove() : 요소를 dom에서 삭제한다.
    (단순히 제거하는구나 하고 넘어갔는데 캠프디스코드에 질문글이 올라왔다. 요소를 remove하고 콘솔에서 요소를 다시찍어봤는데 삭제한 배열이 요소에 포함되어 있다고 보인다는것이다. 그런데 화면상에서는 분명히 삭제되었다. 이에 대한 내용은 추가로 포스트를 해야겠다!)

속성

  • Element.textContent : 요소가 가진 텍스트 콘텐츠를 반환한다.
  • Element.innerText : 마찬가지로 요소가 가진 텍스트 콘텐츠를 반환한다.
    (위 두개의 차이점은 textContent는 노드의 속성으로 해당 노드가 가지고 있는 text값을 다 불러와서 공백이나 자식태그의 내용들도 다 text로 가져옴. 하지만 innerText는 Element의 속성이라서 현재 선택된 태그에서 사용자에게 보여지는 text값만을 반환함. 참조)
  • Element.innerHTML : 요소 내 쓰여진 HTML코드를 텍스트 형태로 반환한다.
    (말그대로 텍스트를 포함한 HTML코드를 통째로 값으로 반환하기 때문에, 태그를 포함하여 값을 할당하면 태그 자체가 수정됨.)
  • Element.className : 요소의 class 속성값을 반환한다.
  • Element.style : 요소의 style 관련 속성값들을 반환한다.
  • Element.title : 요소의 title 속성값을 반환한다.
  • Element.value : <input>, <select>처럼 사용자로부터 입력을 받는데 사용되는 요소에서 입력받은 값을 읽어들일 때 사용하는 속성. 접근과 수정 모두 가능하다.
  • form 요소는 여러 입력 요소를 포함 할 수 있기 때문에 입력값도 여러개인데 이것을 분리하기 위해 요소에 기입된 name속성값을 토대로 접근 할 수 있다. (name은 서버입장에서 요소를 구별하는 값이 되기도 하지만 이렇게 js에서 이벤트를 처리 할때도 유용하다)
    이전에 사용한 textContent와 햇갈릴 수 있을 것 같은데, 요소에 쓰여진 텍스트에 접근하는것은 textContent이고, 사용자가 요소에 직접 입력한 값이 value 인것. 같은 text여도 다르다!
  • Element.ClassList : 요소의 클래스를 담은 객체가 배열의 형태로 반환된다. 관련된 메소드가 다수 존재한다.
    ( ClassName과의 차이 : className은 class를 문자열의 형태로 반환한다. )
    • add('x') : 요소에 'x' 클래스 추가
    • remove('x') : 요소에 'x' 클래스 삭제
    • item(x) : 인덱스를 이용해 클래스 값 반환 item(1)이면 배열에서 1번 인덱스에 있는 클래스값 반환
    • toggle('x') : 클래스 값 토글 x에 해당하는 클래스가 존재하면 없애고 없으면 추가함.
    • contains('x') : 'x'클래스가 존재하는지 여부 확인
    • replace('x', 'y') : 기존 클래스 x를 y로 교체

연산자

  • 위에서 뜨문뜨문 계속 나오는 연산자 총정리

  • 산술연산자 : 숫자를 연산할 때 사용

    • + / - / * / ** / / / %
    • 나머지의 경우 홀/짝을 구분하는등의 경우 많이 사용(ex. 홀수는 나눠서 나머지가 1이 남는 경우 or 컴퓨터로직을 짤 때)
    • 더하기는 문자열에서도 사용 가능. (문자열과 숫자를 더하면 문자열 취급, NaN을 이용한 banana만들기? 해보기)
  • 증감연산자 : 변수의 값을 증감 시킬 때 사용

    • ++ / --
    • 사용하는 위치에 따라 값이 달라짐. 변수의 앞에 사용하면 계산한 후 반환시키고, 변수의 뒤에 사용하면 값을 반환한 후 계산함
  • 비교연산자 : 대소비교(크냐 작냐) / 등가비교(같냐 다르냐)

    • ==(동등연산자)는 자료형은 비교하지않고 그 안의 데이터만 같은지 다른지를 판단하는 것이고,===(일치연산자)는 자료형과 데이터 모두 비교하여 같은지를 판별하는 것이다. 웬만하면 일치연산자를 쓰는 것이 좋은데, 예를들어 동등연산자 배열과 문자열은 완전히 다름에도 빈배열과 빈문자열을 비교하면 둘을 같다고 취급해버린다. 이유는 배열을 문자열로 변환시킬때 [1,2,3] -> '1,2,3' 이런식으로 변환시키는데 배열이 비어버리면 [] -> ''이렇게 변환이 되기때문에 빈문자열과 똑같은 취급을 하는것이다. 이러한 오류가 발생할 수 있어서 사용을 지양하는 것이 좋다.
  • 할당연산자 : 변수에 할당할 때 사용

    • += / -= / *= / **= / /= / %/
    • num = num + 1num += 1로 쓰는 것과 같다.
  • 논리연산자 : 불린값을 다룰 때 사용

    • && / || / !
    • truthy / falsy : js에는 true, false라고 적혀있지 않아도 그렇게 취급하는 데이터가 있다.
      (객체나 배열은 비어있어도 true로 취급한다.)
      ( 여기서 잠깐 삼천포로 빠져서 생각을 했던게 배열이나 객체 안에 undefined만 있으면 빈배열이 아닌가? undefined는 정의된 값이 없다는거잖아 하는 생각을 했다. 정답은 배열 안에 공간은 만들었지만 그 공간에 넣을 값은 정의하지 않았다 인거같다=빈배열이 아니다!@)

조건문

  • 주어진 조건의 참 거짓에 따라 프로그램의 흐름을 결정하는 구문. 여기서 조건이란 boolean데이터를 반환하거나 boolean데이터로 해석할 수 있는 표현식을 의미함. = 불리언데이터로 프로그램의 흐름을 제어하는 선택 제어문

        if(조건1){
            조건이 true일 경우 실행할 코드
        }else if(조건2){
            조건1은 아니지만 조건2는 true일때 실행할 코드
        }else{
            모든 조건이 false일때 실행할 코드
        }
    • else if : 조건이 거짓일 때 그 다음으로 참일경우 아래 포함된 코드를 실행하라.
    • else : 위의 조건들이 모두 거짓이라면 아래 포함된 코드를 실행하라.
    • if만 있을 경우 조건이 false이면 그냥 아무것도 실행하지 않고 끝남. else if는 원하는 만큼 추가할 수 있지만 조건문에서는 만족하는 하나의 조건에 포함되는 코드만을 실행하고 끝마친다.
  • switch문

        switch(표현식){
            case 표현식1:
            표현식 === 표현식1 일 때 행동
            break;
            defualt:
            해당하지 않을때
        }

    괄호에 들어간 표현식과 case의 표현식이 일치하면 case아래에 적힌 코드를 실행함. 주의할 점은 break를 쓰지 않으면 해당 케이스부터 아래의 모든 케이스를 실행함으로 break를 case마다 써주어야함. case, default, break등 키워드가 많고 폴스루가 발생하는 등 문법이 복잡해서 if...else문으로 해결할 수 있다면 사용하지 않는것이 좋지만, if문보다 switch를 사용하는것이 가독성이 좋을때는 사용하는것도 좋다.
    +) 중요한것은 표현식과 case의 표현식 값이 === 일치하는지가 중요하다는것이다. 데이터형식과 값이 모두 같아야한다. 아래 왼쪽의 경우 첫번째 케이스는 일치연산자를 썻기때문에 true나 false라는 값을 반환했을 것이다. 그런데 조건은 num이다. num=0이지 true가 아니기때문에 해당하는 조건이 없어서 default가 실행되는것이다. switch문을 올바르게 실행하려면 조건을 true로 수정해야한다.

  • 삼항연산자

       조건 ? 조건이true일 때 : 조건이false일 때
       : 조건2 ? 조건2가 true일 때
       : 조건2가 false일 때

    if문을 간결하게 쓸 수 있는 장점이 있고, 이름처럼 연산자이기 때문에 결과값이 존재해서 바로 변수에 할당할 수 있다. ( 거의 모든 if..else문은 삼항연산자로 대체 가능)

+) 조건문의 실행 조건이 true라는 것을 잘 기억해야함. 연산자에서 falsy한 값이 존재한다고 했음. 만약에 조건문에 들어간 조건이 0이라면 나는
이것을 false라고 입력하지 않았어도 false로 처리되어 조건문이 의도대로 실행되지 않을 수 있음.

반복문

  • 주어진 조건식의 결과가 참일 경우 코드블럭을 실행하여 거짓일때까지 반복함.

  • for / while / do while / for in / for of 가 있음.

  • for : 주어진 조건식이 거짓일때까지 반복함. 중첩하여 이중반복문으로 사용 가능, 반복 횟수를 알고 있는 경우에 사용하기 좋고 조건식과 초기값이 반복문 안에 있기 때문에 가독성이 좋다.

  • while : 주어진 조건이 참일 동안에 구문을 반복함. while문 내에 초기식이나 반복식을 넣을 수 없음으로 조건이 언제나 참이면 무한루프가 되어 코드블럭탈출조건을 따로 명시해야하고(break)
    조건을 while문 외부에 만들어야함. 반복 횟수를 정확하게 모르는경우(인형을 뽑을때까지 뽑기를 하는 경우)에 사용.

    (confirm()메소드의 경우 취소를 누르면 알아서 false를 반환함으로 이를 이용해서 while문을 사용하면 조건을 따로 기입하지 않아도 됨 while(confirm("반복 실행 할까요?")){코드})

  • for of : 배열 반복문. 인덱스를 사용 할 수 없음.

for (let element of arr){
	배열의 길이만큼 반복문을 시행할 코드
}
  • for in : 객체 반복문.
for(let key in obj){
	객체의 길이만큼 반복문을 실행할 코드
    key를 사용하여 순회하는데, key를 알면 value값도 구할 수 있음.
}

함수

: 호출해서 사용 할 수 있는 코드 조각. 변수를 선언하고 데이터를 대입하면 변수의 이름을 데이터 대신 사용 할 수 있는 것처럼, 함수를 선언하고 기능을 정의하면 함수의 이름으로 코드 조각을 사용 할 수 있다. 메소드를 함수안에 정의하지 않고 바로 코드에 기입하면 내가 원하는 때에 발생시키는것이 어렵기 때문에 함수에 담아두고 원할 때 동작하게 만들 수 있다.

  • 함수를 만드는 방법

    • 함수 선언식
        function 함수명(parameter){
            // 힘수의 기능
        }
    • 함수 표현식
        const 함수명 = function(parameter, parameter ...){
            // 함수의 기능
            return x;
        }

    공통점은 function키워드를 사용하여 함수를 만든다는것으로 함수명은 기능을 정의하는 의미를 담아 동사로 만드는 것이 좋다.(같은 의미로 변수명은 명사로 하는 것이 좋다)
    차이점은 선언문은 호이스팅이 가능하고 표현식은 호이스팅이 되지 않는다는 것이다.

    함수를 작성할때 함수 내부에 사용하는 데이터 값만 바꾸어서 사용할 수 있다면 같은 실행 코드를 사용할 때 매번 다른 데이터 값이 담긴 함수를 새로 작성하지 않아도 된다. 이를 위해 사용하는 것이 인자와 매개변수이다.

    • 인수 argument(전달인자) : 소괄호 안에 함수가 실행 될 때 사용할 재료를 전달 받을 수 있다. 이것을 인수라고 한다.
    • 매개변수 parameter : 인수를 전달받아 기능을 수행하는 함수를 만들때 함수에 인수를 전달하는 매개변수를 추가해야 한다. 매개변수는 원하는 만큼 추가 할 수 있고 쉼표로 구분한다.
    • 반환 return : 함수가 데이터를 반환하도록 할 수 있다. 함수의 호출문이 데이터로 대체됨을 뜻한다. 또 return은 데이터를 반환한다는 의미외에 함수를 강제종료시키는 기능이 있어서 return밑에 코드를 입력해도 return에서 함수가 종료되기 때문에 동작하지 않는다.
    function sayHello(){
        console.log('test')
        return '짠'
    }
    console.log(sayHello());
    // test
    // 짠

    (약간 햇갈렸던 부분인데, 기능과 리턴을 연관 없이 저렇게 써놓고 콘솔에 함수를 표시하면 자신의 기능을 수행하고 리턴값을 반환하여 콘솔에도 찍히게 됨)
    이렇게 함수에 인수를 전달하고 리턴값도 만들 수 있으면 우리가 이제껏 사용했던 객체메소드(alert(), prompt() 등)들 처럼 어떤 특정한 기능을 하는 함수를 우리도 만들 수 있게 된다. 쟤들도 결국 다 함수니까!

    • 화살표함수
        const 함수명 = (parameter) =>{ 
            return x;
        }
    • 규칙 : parameter 1개일 때 소괄호 생략 가능 / parameter 2개 이상이면 불가능 / 함수 코드가 한줄이면 return과 중괄호 생략 가능 / 함수 코드가 한줄이고 객체를 리턴하면 소괄호로 묶기(원래 객체는 소괄호가 있으니까, 화살표함수에서 값을 넣을때는 괄호로 묶어줘야한다) / 함수가 두줄 이상이면 return과 중괄호 생략 불가능.
    let plus = (a,b) => {(a: a, b: b)}

    규칙은 쓰면 깔끔하지만, 굳이 안써도 된다.

고차함수

  • 고차함수를 알기 전에 일급객체부터 알아야 한다.
    일급객체 first class object란 변수에 할당 할 수 있고 / 함수의 인자로 전달이 가능하고 / 함수의 리턴값으로 사용가능한 특성을 가진 객체를 말한다.
    그런데 js를 포함한 몇 언어에서는 함수도 일급객체와 같은 특성을 가져 일급객체로 취급된다.
  • 고차함수는 함수를 인자로 받는 함수 / 함수를 리턴하는 함수라는 특성을 가지는데, 위에서 언급했던것처럼 함수는 일급객체로서 고차함수의 기능을 다 가지고 있기 때문에 고차함수로 동작할 수 있다. 자바스크립트의 대표적인 고차함수 3가지는 map, filter, reduce이다.

콜백함수

이렇게 다른 함수의 매개변수로 사용되어 다른 함수에 의해 호출되는 함수를 콜백 함수라고한다.
보통 일회용으로 사용되기 때문에 굳이 힘수의 이름을 명시할 필요가 없어 '익명함수'의 형태로 작성한다.

  • array.map(함수(현재요소, 인덱스)) : 배열내장메서드로 함수를 전달 인자로 받아 배열의 각 요소에 콜백함수(다른 함수에 인자로 전달되어, 그 함수 내에서 필요한 시점에 호출되는 함수)를 적용시킨 새로운 배열리턴한다.

  • array.filter(함수(현재요소, 인덱스)) : 배열내장메소드로 콜백함수를 적용시켰을 때 결과가 true인 요소만 담은 새로운 배열리턴한다.

  • array.reduce(함수(acc,cur,초기값)): 배열내장메소드, 배열의 요소들을 콜백함수에 맞게 하나의 응축시킨 값을 리턴한다. (문자열, 숫자, 객체, 배열 등)

    arr.reduce(function(acc, cur, 초기값){
        return acc + cur
    })

    위 코드를 예시로 들면 acc은 accumlation으로 응축된값, cur은 current로 현재요소를 말하고 두개의 값을 이용한 결과값이 반드시 존재해야 한다. 함수의 세번째 인자로 초기값을 정하지 않으면 배열의 첫번째 값이 acc값이 되고, 존재하면 그 값이 첫 acc 값이 된다.

  • array.forEach(함수(현재요소, 인덱스)) : map과 비슷하게 배열의 각 요소에 대해 콜백함수를 적용시킨다. 차이점이라면 forEach는 기존 배열을 변경하거나 리턴값이 존재하는게 아니라 콜백함수를 정말로 각 값에 반복하여 실행한다는 것이다. forEach로 호출한 배열을 수정할 수는 있지만 배열의 삭제등에 관여시 배열의 길이가 변경되며 의도치 않은 오류가 발생할 수 있기 때문에 권장하지 않는다. 그렇기 때문에 변수에 할당하지 않고 반복문이나 조건문과 같이 그냥 바로 호출되는 것이 일반적이다.

    • for of 와의 차이점 : 참조. forEach는 for of와 달리 break, continue를 사용할 수 없어서 중간에 반복을 끊을 수 없지만 화살표함수를 사용 할 수 있다. 그리고 forEach는 map, for of와 비교하여 제일 느리다.

이벤트

돔에서 발생하는 다양한 액션 또는 상호작용 동작을 나타내는 프로그래밍 인터페이스라고 하면 좀 어렵고, 버튼을 클릭한 클릭 이벤트, 키보드를 누르는 키다운 이벤트, 폼을 제출한 제출이벤트 등의 웹 브라우저와 사용자 사이에 상호작용이 발생하는 특정 시점을 의미한다.

  • 이벤트 : click, mouseover(마우스를 올릴 때), keydown, keyup, input(입력요소에 값이 입력 될 때 keydown과 다름! 키다운 후 실제로 입력됐을 때 발생함), submit, focus(입력요소에 커서가 깜빡이는 동안! focus에 alert()를 쓰면 신기한 일이 생김. 누르는 순간 alert가 뜨면서 인풋의 focus가 blur되고, 알람창을 끄면 바로 다시 focus 되어서 자동으로 경고창이또 뜸 ㅋㅋ), blur

  • 이벤트 핸들러 : 웹페이지에서 다양한 이벤트가 발생했을 때 어떤 동작을 할지 정리하는 함수.

이벤트 핸들러가 연결된 특정 요소에서 지정된 타입의 이벤트가 발생하면, 웹 브라우저는 연결된 이벤트 핸들러를 실행한다.
웹 이용자가 버튼을 클릭하면 경고을 띄워서 환영메세지를 보여주도록 처리한 예시이다. 각 웹 요소는 저마다 onclick과 같은 이벤트 속성이 정의가 되어있다. 이벤트가 발생할 타겟을 선택하고 이벤트 속성과 이벤트핸들러를 대입한다.
여기서 주의할점은 이벤트핸들러 함수를 등록할 때 소괄호를 붙이면 안된다는 점이다. mdn에서는 해당 내용을 찾지 못했고, chatGPT와 구글링한 블로그에서는 괄호를 붙이는것은 함수 호출로 js해석기는 이것을 즉시 함수를 실행하라! 라고 판단하기 때문에 이벤트가 발생했을 때가 아니라 페이지가 로드되었을 때 이벤트핸들러 함수를 호출한다. 그래서 이벤트핸들러함수를 참조하라는 의미로 괄호를 붙이면 안된다고 한다.

  • addEventListener() : onclick, onkeydown과 같은 이벤트 속성을 통해 이벤트를 요소에 전달하는것 보다 편하고 유용하고 현대적인 이벤트 처리 방법이다.
    이전에 추가한 이벤트 핸들러를 제거할 수 있는 대응 메소드가 존재하고(div.removeEventListener('click', handler)인데, 후술하겠지만 addeventlisterner는 이벤트를 덮어씌우는게 아니라 계속 추가하기 때문에 이벤트를 없앨 메소드도 필요한것. handler는 등록할때 사용한 것을 똑같이 등록하면 되는데, 단순히 함수의 형태로 핸들러를 추가하면 동작만 같은 새로운 이벤트핸들러가 추기되는것이기 때문에 이전에 사용한 함수를 변수에 등록하고 그 변수를 삭제메소드에도 등록하는 식으로 해야함), 같은 리스터(타겟)에 대해 다수의 핸들러를 등록할 수 있다는 장점이 있다.( 앞서 말한 프로퍼티 리스너방식으로 똑같은 요소에 onclick 이벤트를 지정하면 나중에 작성한 코드가 이전에 작성한 코드를 덮어씌워서 하나만 적용이 되지만, addEventListerner로 등록하면 덮어씌우는 것이 아니라 추가가 된다고 한다. 그래서 삭제하려면 add어쩌구이벤트처럼 별도의 메소드 필요없이 div.onclick = null하면 된다. 차이점이라면 전자의 이벤트 등록의 방식은 옛날 버전의 브라우저에서도 적용이 되지만 addEventListerner는 경우 인터넷 익스프로러9부터만 지원이 된다고 한다. 근데 이제 없어졌는데 몰라도 될듯? -mdn 설명중- )
	addEventListener('이벤트명', 이벤트핸들러)
    예시)
	button.addEventListener('click', function(){
    	// 실행할 이벤트 내용
    })
  • 이벤트 객체 : 이벤트가 발생하면 프로그램 내부적으로 이벤트 객체가 만들어지고 원하면 이것을 사용 할 수 있다. 이밴트 객체는 이벤트와 관련된 추가적인 기능과 정보를 제공하기 위해서 이벤트핸들러에 자동으로 전달되는 데이터이다. 이것을 이벤트핸들러에서 활용하려면 매개변수로 추가하여 이벤트가 발생할때마다 이밴트핸들러가 전달받을 수 있도록 하면 된다.
    (아래 두번째 이미지는 event를 console에서 확인해본것)(이벤트 객체를 활용한 예시. form submit은 기본적으로 제출할 때 페이지가 새로고침된다. 실습할때는 제출과 새로고침의 동작이 필요하지 않고 이벤트 등록만을 연습해볼것이기 때문에 위와 같이 이벤트 객체에 기본적으로 등록된 기능인 e.preventDefault()메소드를 사용하면 제출이 되면서 새로고침 되는 동작을 막을 수 있다. 그러니까 제출도 안되는게 맞다! 참조)
  • 이벤트 등록
    • 인라인 이벤트 핸들러 : HTML 코드에 style을 직접 적용 하는것처럼 이벤트도 직접 적을 수 있지만 권장하지 않는다. 코드를 분리하지 않고 함께 쓰면 분석하기 힘들어져 SEO에 불리해지고, 작성한 이벤트를 재사용하기 힘들어진다.
    • 프로퍼티 리스너 방식 : 함수 선언식, 표현식 모두 가능
      뭘 사용하던 상관없지만 표현식(아래)이 더 많이 사용되는데 간편하기 때문이다.
    • 아까 공부한 addEventListener()방식으로 이벤트 등록하기가 가장 추천된다.
  • 이벤트 버블링 / 캡쳐링
    • 넘우나 조은 설명 사이트 : https://ko.javascript.info/bubbling-and-capturing
    • 내가 짧고! 간단하게! 정리해보자면
      특정 이벤트가 발생하면 그 순서는 최상위 요소에서 이벤트가 발생한 타겟요소까지 전달되는 캡쳐링단계 / 그리고 실제 타겟에서 이벤트가 실행되는 타겟단계 / 타겟단계부터 다시 상위요소로 이벤트가 진행되는 버블링단계를 거친다.
      기본적으로 이벤트를 등록하면 이벤트핸들러는 버블링으로 동작하도록 되어있다.이는 버블링의 강력한 이점인 이벤트 위임때문이다. 이벤트 위임은 상위요소에 등록한 이벤트가 하위 요소에서도 동작하는 것이다. (이게 왜 캡쳐링이 아니라 버블링이야?! 하고 처음에는 이해가 안됐는데, 버블링을 다시 차분히 살펴보면 하위요소의 이벤트를 발생시키면 상위요소의 이벤트까지 연속으로 발생되는 것을 말한다. 즉 상위요소에만 이벤트를 등록시켜놔도 하위요소를 클릭하는 등의 이벤트를 발생시키면 버블링이 발생하면서 상위요소의 이벤트까지 발동되게 되는것이다. 만약 임의로 리스트같은것들을 추가시키는 상황에서 일일이 추가한 요소에 이벤트를 추가하는 것이 아니라 상위요소인 ul에만 이벤트를 등록시켜 놓으면 임의로 추가한 리스트에 이벤트를 하나씩 추가하지 않아도 버블링을 사용해서 ul의 이벤트를 동작 시키면 되는것이다. 예를들어 li를 클릭하면 삭제하는 이벤트를 ul에 등록해놓고, li를 추가 한 후 클릭하면 버블링으로 ul의 이벤트가 발동되어 li가 삭제되는것이다.)
      버블링은 대부분의 경우 이점이 많지만 이것을 막으려면 event.stopPropagation()을 사용하면 된다. 캡쳐링으로 이벤트를 처리하는 방법은 이벤트를 등록할때 핸들링함수 뒤에 true인자를 추가하는것이다. 그러나 거의 쓸일은 없다고 한다.
      event.target은 실제로 이벤트가 발생한 지점이고 this(=event.currunttarget)은 현재 이벤트가 실행되고 있는 지점을 말한다.

빌트인 생성자와 객체

js는 개발자의 편의를 위해 유용한 기능을 제공하는 빌트인 생성자 또는 빌트인 객체를 지원한다.

  • 빌트인 생성자 : 자바스크립트에 내장된 생성자로 이를 이용해서 객체를 생성 할 수 있다. 예) Object(), Arrey(), Date()
  • 빌트인 객체 : 자바스크립트에 내장된 객체로 이를 이용해 특정 값이나 기능을 호출 할 수 있다. 예) Math, Date, Array 등
  • date는 빌트인 객체이면서 생성자 함수이다.

대표적으로 많이 사용하는 빌트인 생성자는 Date()가 있다.

  • const now = new Date() 생성자니까 new와 함께 사용해서 새로운 객체를 리턴해야 한다. 코드가 실행되는 시점의 날짜와 시간정보를 담고있다.
    getFullYear, getHours 등의 소것ㅇ과 메소드들을 포함하고있다.(년,월,일,시,분,초를 다 따로 가져 올 수 있으며 인자로 전달할 경우 해당하는 날의 시간정보를 담을 수 있다.)
  • date와 함께 추가로 알면 좋은 js의 메소드로 setTimeout, setInterval이 있다.

빌트인 객체로는 Math가 있다.

  • 생성자가 아님으로 Math()와 같이 사용하면 에러가 나고

  • Math.메소드() 와 같이 내장된 메소드를 사용하여 수와 관련된 작업을 할 수 있다.

    • abs(x) : x의 절대값을 반환
    • floor(x) : x보다 작거나 같은 수 중에서 가장 큰 정수를 반환
      console.log(Math.floor(5));
      // Expected output: 5
    
      console.log(Math.floor(-5.05));
      // Expected output: -6
    • pow(x, y) : x를 y만큼 제곱해서 반환
    • random() : 0이상 1미만의 난수를 반환. 여기서 나온 값을 곱하거나 더하는 등의 작업으로 원하는 범위를 만들어서 사용하는 경우가 많음.
      (예를들어, 1~10의 숫자를 랜덤하게 뽑고싶으면 Math.random * 10 + 1을 해야함. 더하기 1을 해주지 않으면 0이상 10미만!! 미만이기 때문에 10은 안나오고 10보다 작은 값들만 나오고 0도 나올 수 있음. +1을 하면 1부터 11미만!!의 숫자가 나오기 때문에 1~10사이의 랜덤한 숫자를 받을 수 있음.
      이를 이용해서 10의자리에 최대값, 1의 자리에 최소값을 넣는 변수를 만들어서 사용 할 수도 있음.)
    • sign(x) : x가 양의 숫자인지 음의 숫자인지 나타나낸 부호를 반환 (-1 or 1)
    • sqrt(x) : 주어진 숫자의 제곱근을 반환. 4의 제곱근은 2

JSON

  • 빌트인객체로 JavaScript Object Notation의 줄임말이다. 자바스크립트 객체를 문자열로 표현하는 데이터 포맷으로 주로 js에서만 사용할 수 있는 객체타입을 다른 프로그래밍 언어에서도 사용할수 있는 형태의 문자열로 변환하기 위해 사용한다.
  • 객체를 변환한것이기 때문에 문법적으로 객체리터럴형식을 따르지만 괄호밖, key를 따옴표로 감싸주는것 외에는 그대로 표기한다.
  • 보통 주석을 달지 않는다.
  • JSON 메소드
    • JSON.stringify(x) : 객체를 JSON 형태로 전환하여 반한 (undefined, 함수등은 생략되거나 null로 반환)
    • JSON.parse(x) : JSON을 객체로 전환하여 반환. 작은 따옴표나 후행쉼표는 파싱이 불가하기도 하다.

내장함수

  • 프로그래밍 언어의 실행 환경 또는 표준 라이브러리에 이미 구현되어 있는 함수로 별도의 작업 없이 바로 사용하다. parseInt(), console.log(), alert(), setTimeout() 등등

  • setTimeout : 정해진 시간이 지나고 나서 주어진 함수를 실행해주는 타이머 메소드

      setTimeout(실행할함수, ms단위의 시간)
      ///1000ms = 1초
  • setInterval : 일정한 간격에 따라 함수를 반복 실행 할 수 있도록 해주는 타이머 메소드

    setInterval(반복실행할 함수, ms단위의 시간)

    setInerval은 실행되면 0이 아닌 숫자를 반환하며 해당 타이머의 ID가 된다. 이것을 clearInterval(id)에 등록하고 실행하면 반복을 멈출 수 있

객체 생성자

자바스크립트에서 그냥..너무 중요한..객체..!!! js 자체도 객체로 이뤄져있고, dom도 객체이고 또 그 객체를 다루는 것이 js이고.. 그렇기 때문에 앞으로 내가 다루게 될 정보들도 보통 객체의 형태를 띄게 된다.
그래서 빌트인 생성자 중에서도 객체를 만드는 방법과 객체를 이용하는 방법에 대해서 알아야 한다.

  • 키와 값으로 구성된 속성의 집합인 객체를 {}를 이용해 직접 생성하는 것을 객체리터럴 방식이라고 한다.
    ( 리터럴이란, 코드상에 직접 나타나는 데이터의 값 자체라고 할 수 있다. 예를들어 let x=10;에서 x는 변수이고, 10은 리터럴인데 숫자이기 때문에 숫자형리터럴이다. 객체리터럴이라는건 객체값 그 자체를 직접 만든다는 의미.)
const person = {
  name:'홍길동' // key:name, value:'홍길동'
}
  • 객체는 데이터의 종류를 가리지 않고 몯느 자료형의 데이터를 값으로 가질 수 있음. 객체안에 또다른 객체나 함수가 포함 될 수도 O.
  • 객체의 키는 문자열로 작성하는데 따옴표를 표시하지 않아도 되지만, 공백이 포함 됐을 때는 표시해야하고 대괄호연산자를 사용해야함.
  • key는 중복 될 수 없음.
  • 생성자함수 : 객체리터럴 외에 객체를 만들어내는 방법으로, 함수의 형태를 이용해서 만든다.
function Person() {
  this.name = "홍길동";
  this.age = 20;
  this.gender = "남자";
}

this는 자기 자신을 의미하며 생성자 함수를 호출한 객체를 말하고, new를 붙여서 생성자함수를 호출하면 생성자로서 동작한다.
생성자 함수는 객체를 이렇게 만들겠다 라는 정의일 뿐이며 실제 객체가 생성되려면 new연산자를 붙여야 객체가 반환된다.

  • 생성자함수에 의해 생성된 객체를 인스턴스instance라고 한다. 매개변수로 값을 전할 수 있다. 관례상 생성자 함수명의 첫글자는 대문자로 한다.
let person = new Person();
console.log(person); // Person { name: '홍길동', age: 20, gender: '남자' }

function Person(name, age) {
  this.name = name; // 이 생성자 함수 Person을 사용해 만든 인스턴스는 매개변수로 전달 된 name을 변수 name에 할당합니다.
  this.age = age; // 생성자 함수 Person을 사용해 만든 인스턴스는 매개변수로 전달 된 age를 변수 age에 할당합니다.
  this.gender = "남자";
}
  • 생성자함수에서 알아야 할 중요한 점은 새로운 객체를 만들어 낸다는 것이다. 똑같은 값을 넣어서 똑같이 생긴 객체를 만들어도 둘은 같은 객체가 아니다! 새로운 데이터의 객체를 만들었기 때문이다! 생성자함수를 사용하는것은 많은 객체를 만들어야 할때 객체리터럴로 일일이 만들어 주는것보다 재사용성이 좋다.

배열 생성자

빌트인생성자 중에서 객체만큼이나 중요도가 탑급인 배열에 대해서도 공부해야한다..!

  • 배열리터럴
const arr = [1,2,3]
  • Array 생성자
const arr = new Array(1,2,3)
// 초기값으로 하나의 숫자를 주면 그 길이만큼 빈값이 들어있는 배열을 만들어냄.
const arr1 = new Array(3);
console.log(arr1); // [undefined, undefined, undefined]

배열에서 알아야 할 사항은

  • 배열에 포함된 값 하나하나를 배열 요소라고 하며 보통 item이라고 한다.
  • 각 배열 요소는 왼쪽부터 순서가 매겨지며 이것을 index라고하고 0부터 시작한다. 인덱스는 대괄호연산자를 이용하여 해당 인덱스 번호의 item을 참조할 수 있다. arr[0], arr[1] 참조할 수 있다는 것은 곧 이것을 읽거나 쓰는 등의 작업도 가능하다는 뜻이다.
  • 배열 요소 수는 원하는 만큼 포함시킬 수 있으며 0개 일 수 있다.(확실하게는 43억개=2^32-1만큼의 요소를 가질 수 있음. 조금 궁금해서 찾아봤는데 이것은 js에서 다룰 수 있는 정수의 한계와 같다고 함. 배열은 0부터 시작하기 때문에 -1 해주는것)
  • 숫자, 문자열, 객체, 함수 등 모든 데이터를 담을 수 있다.
  • 배열은 객체이기 때문에 수많은 메소드와 속성이 정의되어 있다.

    배열을 콘솔에 찍어서 확인해보면 prototype에 Array가 뜬다. 시제품의 형태가 배열을 기반으로 하고 있다는 표현이다.

참조자료형 복제

  • 참조자료형인 객체나 배열은 단순히 변수에 할당하는 것으로는 그 값을 복제 할수가 없어서, 특별한 메소드를 사용해야 한다.(초반에 언급했지만 참조자료형은 변수에 할당해도 메모리의 주소만 참조할 수 있기 때문에, 기본적으로 가지고 있던 변수나 객체의 형태를 유지하면서 똑같은 값을 가진 다른 배열이나 객체로 테스트를 해보려면 그 값을 복제해야하는데 원시자료형처럼 해서는 안되고 새로운 메모리 공간에 객체나 배열을 만드는 메소드가 필요하다 )

  • 공통적으로 스프레드 연산자 ...를 사용하면 배열이나 객체의 값을 풀어서 넣는다는 의미가 되어서 특별히 메소드를 사용하지 않아도 복제 할 수 있다.

    배열 1과 배열 4를 비교하면 두개는 같은값이라고 나오지만, 배열1과 배열2, 배열3을 비교하면 안에 담긴 배열의 값은 같아도 false가 반환된다. 새로운 메모리에 만든 다른 배열이기 때문이다. 객체도 마찬가지다.

  • 얕은복사 vs 깊은복사 :

배열이나 객체를 복제하여 새로운 메모리 주소를 할당할 때 내부에 또 배열이나 객체가 존재한다면 그것역시 값 자체가 아니라 메모리주소에 대한 정보를 담고 있는것이기 때문에 내부에 존재하는 참조데이터의 주소는 변하지 않는다. 이것을 얕은 복사라 하고, 반대로 내부의 참조형의 메모리주소까지 재할당하는것을 깊은 복사 라고 한다.

  • 깊은 복제를 하는 방법으로 ladash 라이브러리를 사용하거나, JSON.stringfy() / JSON.parse()메소드를 사용 할 수 있다. 각각 배열이나 객체를 문자열로 전환, 문자열을 다시 배열이나 객체로 전환시키는 기능이다.
    이 메소드를 사용한 전환과정을 통해 변수에 저장하면 전체 값이 수정되면서, 새로운 메모리를 할당하고 그 주소를 참조하기 때문에 깊은 복사가 된다.
    그러나 이 방식의 맹점은 함수나 undefined와 같은 값은 변환이 되지 않고
    또 객체의 경우에는 순서가 중요한 배열과 다르게 객체는 그 안에 든 값자체가 중요하기 때문에 담긴 키와 값이 같으면 순서가 다르더라도 같은값으로 판단하는데, JSON.stringfy()를 사용하면 문자열이 되어버려서 순서가 다르면 다른값으로 인지하는 문자열의 특성과 반대되어 값을 비교하는 등의 상황에서 올바르게 사용 할 수 없다.
    (이 설명이 나온 이유는, 아까 위에서 배열1!==배열3인 상황이라면 배열의 값 자체가 같다고 판단할때는 어쩔수없이 반복문을 사용해야 하나요? 라는 나의 질문에 대한 대답이었다. 반복문을 사용해도 되지만 JSON.stringfy()를 사용해도 되는데 배열은 비교가 되지만 객체는 이런방법으로 비교할 수는 없다는 것이었다.)
    그래서 이러한 형태를 띄는 재귀함수를 사용하여 객체나 배열이 몇겹으로 쌓여도 모두 새로운 값으로 바뀌도록 하는것이 가장 올바른 방법이지만, 재귀함수를 사용하여 깊은 복사를 해야할정도의 데이터는 훌륭한 구조는 아니라고 판단하기도 한다.

이걸 처음에는 왜 알아야 하지..? 했는데 실습을 해보니 얕은복사와 깊은복사의 차이점, 그리고 참조자료형의 메모리 주소 참조에 대해 잘 알아야 배열과 객체를 다룸에 있어서 오류를 적게 발생 시키면서 의도대로 동작하는 프로그래밍을 할 수 있을 것 같다!

배열과 객체 메소드

위에 이어서 내장객체에 포함된 배열과 객체를 다루는 메소드들!

  • slice : 그냥 복제에 사용 할 수도 있고, 인자를 넣을 수도 있는데 첫번째 인자로 받은 값에 해당하는 index에서 시작해 해당 인덱스의 값을 포함하여 두번째 인자로 받은 값에 해당하는 index의 전까지 복제하고 새로운 배열로 반환함. 원본배열은 수정되지 않음. 두번째 매개변수로 - 의 값을 넣으면 제일 뒤의 인자부터 -1의 인덱스를 부여하여 똑같이 동작함.
    하나의 값만 넣으면 그 인덱스를 포함하여 끝까지 복제함.
	let arr = [0, 1, 2, 3, 4, 5]
    let copy = arr.slice(1,4)
    console.log(copy) // [1, 2, 3]
    
    copy = arr.slice(1, -1) // [0, 1, 2, 3, 4]
    
    copy = arr.slice(3) // [3, 4, 5]
    copy = arr.slice(-2) // [4, 5]
    
  • splice(x, y, z) : 기존의 배열에서 요소를 삭제 혹은 추가한다. x는 시작인덱스, y는 시작 인덱스를 포함하여 그로부터 몇개의 값을 삭제할지, z는 삭제된 자리에 어떤 값을 추가할지를 정하며 z값은 원하는 만큼 넣을 수 있다.

  • join(x), split(x) : 배열을 문자열로 만들고, 문자열을 배열이나 객체로 만들 수 있음. 인자는 기준값이 됨.

    let arr = [1,2,3]
    arr.join() // 1,2,3
    // 1,2,3을 다시 스플릿
    arr.split() // ['1', '2', '3']
    // 맨처음의 배열에 적용
    arr.join(-) // 1-2-3

    주의사항은 문자열을 배열로 만들기 때문에 값에 따옴표가 추가됨.

  • concat은 앞 뒤 배열을 연결하는데, [...arr1, ...arr2]와 같이 스프레드 연산자를 사용해도 됨.

  • push : 원본배열의 마지막에 요소 추가후 변경된 배열의 lenght를 반환

    let result = arr.push(3, 4);
    console.log(result); // 4

    이런식으로 변수에 담으면 배열에 변수를 담고 그 후 배열의 길이를 반환함

  • pop : 원본 배열의 마지막 요소 제거 후 제거한 요소 반환

  • unshift : 전달인자로 받은 모든 값을 원본 배열의 선두에 추가 후 길이 반환

  • shift : 배열의 첫번째 요소 제거 후 제거한 값 반환

  • entries는 자주 사용되지는 않는다.

spread연산자

  • ... 주로 배열과 객체를 다루는데 사용되며 요소목록을 펼칠 수 있다. 전개구문, 전개연산자 등으로 불린다.
  • 사용된 자리에 개별 요소를 '놓고나온다'는 느낌이다.
  • 배열을 복제하는데 유용하다.

Local storage

  • 로컬 저장소는 웹브라우저에서 각 도메인(현제 보고있는 주소)에 할당해주는 저장공간으로 데이터를 영구적으로 보관할 수 있다. 그래서 브라우저를 껐다 켜거나 새로고침해도 해당 도메인에 데이터가 남아있게된다. 개발자도구에서 확인 할 수 있다.

  • 데이터 보관 시에는 데이터의 이름과 데이터의 실제 값을 각각 지정하며 둘 다 문자열의 형태만 허용한다.

  • js에서 window.localStorage속성은 현재 도메인의 로컬저장소에 접근할 수 있게 해준다.

    • localStorage.setItem('key', 'value') : 키와 밸류를 전달받아 저장
    • localStorage.getItem('key') : 전달받은 키에 해당하는 밸류를 반환
    • localStorage.removeItem('key') : 전달받은 키에 해당하는 데이터를 삭제
    • localStorage.clear() : 모든 데이터 삭제
  • 문자열만 허용한다는 것은 아래 이미지처럼 배열을 저장하면 그것을 텍스트 그대로 [배 열] 하고 저장한다는 것이다.
    그래서 local Storage에 값을 저장하고 불러올때는 JSON메소드를 사용하여 JSON형태를 사용한다.

객체 지향 프로그래밍

Object Oriented Programming, OOP

class 문법

  • 자바스크립트에서 OOP를 구현할 수 있도록 만들어진 문법이 class문법이다.
  • 그런데 결과를 보면 생성자 함수를 이용해 만든 객체와 유사하다. 차이라면 객체는 함수가 드러나있지만 class는 prototype에 들어가있다.

Prototype

  • 위에 이어서, 왜 객체리터럴과 class에 차이가 있는지를 알려면 프로토타입을 알아야한다.

  • 프로토타입이란 번역하면 원형객체라는 뜻이다. OOP의 특징중에 하나였던 상속을 위해 구현된 개념으로 자바스크립트는 프로토타입 기반 언어(prototype-based language)라 불린다. 모든 객체들이 메소드와 속성들을 상속 받기 위한 템플릿으로써 프로토타입 객체(prototype object)를 가진다.

  • 원래 객체인 Array가 존재하고, 그 Array를 상속받아 만들어지는 arrArray의 값이나 기능을 상속하여 arr에서도 사용할수 있도록 만들려면 해당 객체 생성자의 prototype이라는 속성에 값과 기능을 정의하여야 한다. 즉 Array객체를 상속하고싶으면 Array의 prototype속성에 값을 저장해야 한다는 말이다. (이미지의 오른쪽과정)

  • 상속되어 만들어진 arr에서 상속받은 값을 확인하려면 = 자기가 어떤 객체에서 상속되었는지 확인하려면 반대로 왼쪽 과정을 거치면 된다.

  • 우리가 사용하는 배열이나 객체에서 사용한 pop(), map()같은 메소드를 직접 정의한적이 없는데도 사용할 수 있는것이 바로 이 상속 덕분이다.

  • 다시 처음에 언급한 왜 객체리터럴과 class는 함수를 숨기고 드러내는 차이가 있는가하면, 객체리터럴은 같은 객체생성자함수에서 만들어졌다고 해서 상속이 되지 않는다.

    그러나 class는 만들면서 그 값들을 모두 상속해 줄 수 있기 때문에 프로토타입에 함수가 등록되는 것이다. prototype을 명시하고 복사를 해주고 부모요소를 표시해주는 등의 과정을 거치면 객체리터럴로 만들어진 객체도 상속해줄수 있지만 과정이 복잡하고 재사용하기 번거롭기 때문에 상속을 위해 위 과정을 간단하게 정리한 class문법이 만들어진것이다.

  • class 상속 하는 방법 어디에서 상속받았는지 extends에 써주고, 상속받을 값을 super에 한번에 기입한다. 값이나 메소드를 추가하려면 class를 만들때와 같이 추가하면 되고, 수정할 때는 덮어씌우듯이 재설정해주면 된다. 그러면 학생객체는 사람객체를 상속받아서 사람객체의 값과 메소드를 참조 할 수 있다!

Scope

한글로 번역하면 범위. 프로그래밍적으로는 변수에 접근할 수 있는 범위를 말한다.
예를들어, 위 코드를 실행하면 지역변수 is not defined라는 오류가 난다. 콘솔이 화면에 지역변수를 보여주기 위해 찾았지만 정의된 값이 없다는 말이다. 이것은 지역변수가 함수()안에서 정의되어 해당 범위 안에서만 참조 할 수 있기 때문이다.

그런데 함수();는 실행해도 오류가 나지 않는다. 전역변수는 어떤 범위 안에 포함되지 않고 외부에 선언됐기 때문에 모두에게 참조될 수 있다.

이렇게 선언된 위치에 따라서 변수에 접근할 수 있는 차이가 존재하는 것을 스코프라고 하는데 6종의 비교가능한 스코프가 있다.

  • 전역스코프 vs 지역스코프 : 전역스코프는 말 그대로 전역(모든곳)에서 접근 가능한 변수 / 지역스코프는 특정 지역에서만 접근 가능한 변수

  • 함수스코프 vs 블록스코프 : 함수 범위 안에서만 접근 가능한 변수 / 블록 범위 안에서만 접근 가능한 변수

  • 렉시컬스코프 vs 동적스코프 : 함수를 정의하는 순간 정해지는 스코프 / 함수를 호출하는 순간 정해지는 스코프
    렉시컬스코프는 자바스크립트의 동작방식으로, 함수가 정의되었을 때 스코프가 정해지기 떄문에 스코프확인() 함수가 선언 됐을 때 앞에서 만들어진 "안녕하세요"를 참조한다.
    동적스코프는 호출될때 스코프가 정해지기 때문에 확인할변수를 바로 위에 있는 "hello"를 참조한다.

  • 이렇게 하위 스코프에서 자신의 상위 스코프로 이동하며 참조할 변수를 찾는것을 스코프체이닝이라고 한다. 반대로 상위스코프가 하위스코프의 변수를 참조하는 것은 불가능하다.

렉시컬스코프와 스코프체이닝에 대해 알고있으면

Closure

를 이해할 수 있다. 클로저는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합인데 말이 좀.. 어렵지만 풀어보면

주변상태란 lexical scope를 말한다.
즉, 렉시컬스코프환경에서 변수가 스코프체이닝 방식으로 참조할 값을 찾는 것을 이용하여 만들어진 함수들의 조합을 말한다.

카운터만들기()카운터올리기를 반환하기 때문에, 카운터만들기()를 실행하면 카운터올리기()가 동작하여 카운트를 1 증가시킨다.

즉, 카운터만들기()내부에 선언되어 원래라면 참조할 방법이 없는 카운트카운터만들기()가 리턴한 카운터올리기()로 조작 할 수 있게 된다. 이것이 clozer다.

  • 클로저의 장점
  1. 재사용성 : 위 예시와 같은 클로저를
    const 카운터2 = 카운터만들기();
    const 카운터3 = 카운터만들기();
    const 카운터4 = 카운터만들기();
    이런식으로 여러개 만들면, 각각의 카운트값은 따로 해당 함수 안에서 조작됨으로 독립성도 높고, 재사용하기도 좋다.
  2. 데이터 은닉 : 카운트변수는 그것을 조작하는 카운터올리기()함수안에 선언된것도 아니고, 카운터만들기() 외부에서 콘솔을 찍는 등의 확인할 방법이 없기때문에 이 데이터에 접근은 오로지 함수를 호출하는 것 밖에 없음. 이런식으로 노출되어선 안되는 데이터를 은닉하기에 좋음. 아래는 또다른 예시.

ES6에 추가된 주요문법

spread, Rest, 구조분해할당은 배열과 객체를 편리하게 사용할 수있게 돕는 도구이다.

spread 연산자

... : 한글로 번역하면 펼치다, 퍼뜨리다라는 뜻이다. 말그대로 이 문법을 사용하면 배열이나 객체에 든 값을 펼쳐 볼 수 있다. 안에 든 값만 꺼내온다는 느낌이다.
확인해보면 arr만 콘솔에 찍으면 배열 그 자체가 나오지만 스프레드연산자를 붙여서 사용하면 내부에든 값 1 2 3을 보여준다.
배열에 사용해보면 기존의 배열은 해치지 않으면서 가지고 있는 내용을 모두 집어넣고 새로운 항목을 추가한 모습이다. 객체에서도 마찬가지로 동작한다. 여러번 사용 할 수도 있다.

이런식으로 스프레드연산자는 배열이나 객체를 복제하거나 합쳐서 새로운 값을 만드는데 사용될 수 있다.

rest와 비구조화할당

... : 생김새는 같지만 spread가 값을 펼친다면 rest는 반대로 모은다. rest는 객체, 배열, 함수의 파라미터에서 사용한다.

  • 이런식으로 함수에 여러개의 파라미터를 전달해야 할 때 일일이 기입해 줄 수 도 있지만, 수가 많아지고 몇개가 전달될지 모르는 상황일 때 rest를 사용하면 파라미터와 인자의 수가 달라 NaN가 출력되는 상황을 방지할 수 있다.

  • 비구조화할당 혹은 구조분해할당은 배열이나 객체의 구조를 분해하여 변수로 할당하는 문법이다.

    성1, 이름1 처럼 인덱스를 이용하여 할당할수도 있지만 성2, 이름2처럼 구조분해할당을 이용하면 편리하다.

    배열이 순서대로 담아준다면, 객체는 key를 확인하고 값이 같으면 할당해준다.

  • 함수와 객체에서 rest를 사용할 때는 구조분해할당과 같이 사용된다.

    color에는 보라색이 할당되고, 나머지값은 slimes에 담긴다. 이런식으로 rest는 값을 펼치는것이 아니라 하나로 모아준다.
    spread는 배열이나 객체를 합치거나 값을 추가해주기 위해 사용했다면, rest는 보라색슬라임에서 색깔을 빼고 슬라임만 남긴것처럼 특정 값을 제거하기 위해서도 사용 할 수 있다.

동기 / 비동기

비동기데이터통신

비동기 데이터 통신에 앞서서 HTTP에 대해 먼저 공부해야한다.

  • HTTP : HyperText Transfer Protocol은 웹을 통해 클라이언트와 서버가 데이터를 주고받을 때 사용하는 방식의 이름으로 웹에서 이뤄지는 모든 데이터 교환의 기초이다. 이것을 암호화하여 보안을 확보하면 HTTPS라고 한다.


    이런식으로 클라이언트가 서버에게 요청메세지를 보내고 이에 대해 서버가 메세지를 응답하는 방식이 HTTP이다. 서버는 해당 작업을 마치고나면 마치 클라이언트와 연관된적이 없던것처럼 초기상태로 돌아오는데 이러한 특징떄문에 HTTP를 stateless규약이라고도 한다.

    내가 벨로그를 보고싶어서 주소에 http:벨로그주소 라고 인터넷을 통해 서버로 보내면 벨로그 서버는 해당하는 html문서를 보내어 응답한다.

  • HTTP 요청의 3가지 구성

    • 요청행 : 요청메소드, URL, HTTP 버전정보 등
    • 요청헤더 : 메시지정보, 메시지에 저장한 데이터 정보 등
    • 메시지본문 : 서버측으로 보내는 데이터를 포함

    HTTP 요청에는 위의 3가지 구성요소가 있어야하느데 이중 눈여겨봐야 할것은 요청메소드로 초반에 공부한 GET, POST가 바로 요청메소드이다. 구성에 필요한 요소를 기입하면 웹에서 틀을 갖춰서 전송해준다. 총 9개가 있고 그중 자주 사용하는 5종은 아래와 같다.

  • HTTP 응답의 3가지 구성

    • 응답행 : 상태코드, 보충메시지, HTTP 버전정보 등

    • 응답헤더 : 메시지정보, 메시지에 저장한 데이터 정보 등

    • 메시지본문 : 클라이언트측으로 보내는 데이터를 포함

      여기서 눈여겨봐야 할것은 상태코드로, 요청이 성공적으로 완료되었는지를 보여주는 상태코드이다.200은 성공 / 400번대는 보통 요청 정보가 잘못되었다는 의미로 401은 비밀번호나 암호화 오류 / 403은 접
      근권한이 없음 / 404는 제대로된 주소를 기입하지 않았을 때 / 500번대는 서버오류

XMLHttpRequest

통신이 어떻게 이루어지는지 파악했다면 어떻게 프로그래밍으로 구현하는지 살펴보자.

XMLHttpRequest는 서버와 상호작용하기 위해 사용하는 js의 빌트인 생성자이다. (생성자니까 new로 호출해야한다) 이것을 이용하면 서버로부터 데이터를 받아와 전체 페이지의 새로고침 없이도 페이지의 일부만 업데이트하는 비동기방식의 데이터통신을 수행 할 수 있다.

이러한 프로그래밍기법을 Ajax라고 한다. (Asynchronous JavaScript And XML) Ajax는 웹서버와 비동기로 통신하고 DOM을 이용하여 웹페이지를 동적으로 갱신하는 프로그래밍 기법이다.

  • 사용흐름
  1. new연산자를 사용해 XMLHttpRequest 객체 생성
  2. 서버와 통신할 떄 필요한 정보 및 처리방법 기입
  3. 요청을 전송해 통신을 시작

비동기 통신을 시작하면 서버와의 통신상태를 감지할 수 있다. 이 때 발생하는 이벤트는 이벤트핸들러에 등록할 수 있다.
주의깊게 봐야할 것은 load이다. 로드가 됐을 때 응답받은 값을 활용하여 dom을 조작 할 수 있다.

  • 사용방법은 위 이미지와 같다.

    이미지에서 사용된 주소는 DOG API로 서버로부터 요청을 응답받는 연습을 할 때 사용되는 오픈소스 데이터 통신 api로 요청을 보내면 무료로 개발된 랜덤한 강아지 이미지로 응답해준다.

    생성자를 변수에 담고, .open('통신방식', 'url') 메소드를 사용하여 요청양식을 작성하고 .send 메소드로 전송한다.
    load에 성공했다는 것을 확인하기위해 예제에서는 알림창을 뜨게 했고 실제로
    알림창이 뜬다.

    이렇게 load = 통신에 성공하면 rqs객체에는 response라는 응답된 데이터 업데이트된다.
    response를 콘솔에 찍어서 확인해보면 다음과 같이 JSON형태로 응답을 받은 것을 알 수 있다. 해당 주소를 검색해보면 강아지 이미지가 확인된다.
    실제로 활용할때는 JSON형태이니 JSON.parse를 이용하여 객체형태로 반환하면 js에서 사용 할 수 있다. 위 코드는 버튼을 누르면 통신을 시작하여 응답을 받으면 img의 src를 수정하여 이미지를 화면에 띄운다. 이렇게 받은 데이터를 활용하여 브라우저에 띄워보면 강아지 사진이 뜨는데도 전체 화면이 새로고침 되는 것이 아니라 해당 영역만 변경되는 것을 볼 수 있다.

추가

  • Intl internalization 국제화
    : 여러 가지 언어로 서비스를 할 수 있도록 웹 애플리케이션을 설계하고 구현하는 과정을 흔히 국제화(internalization, i18n)라고 한다.(출처)
    웹페이지 상에 사용된 문구들을 단순히 번역하여 표시해주는 것만 뿐만 아니라 동일한 데이터를 언어나 지역별로 다른 형식으로 보여줘야 한다.
    이를 해주는 api가 intl api이다. 대부분의 브라우저에서 지원한다.
    대표적으로 date, time, numbers, relative time 등이 있다.
    date를 한국식으로 표현했다.이렇게 다양한 옵션을 줄 수 있다. 첫번째 예시는 year을 2글자만 표시하도록해서 2024년이아니라 24년으로 표시된다.숫자의경우 한국식으로 3자리마다 콤마가 찍히도록 할 수 있다.옵션으로 숫자를 퍼센테이지로 표시했다.시간이 상대적으로 얼마나 흘렀는지 표시한다.

3.29 자바스크립트의 첫 난관은 역시 개념을 이해하는 것 같다. 객체라던지 변수라던지 평소에 한글로 대화할 때 잘 사용하지 않는 단어들이 나오면서 이게 무슨뜻이었더라? 에 집착하다보니 (문과라그런가?) 햇갈릴 때가 있었는데 이번에 여러 설명을 보고 정리하다보니 예전보다 개념에 대해서 많이 정리가 되었다. 또 녹화강의 외에도 노션에 정리 자료를 올려주신게 정말 도움이 많이되었다. 강의는 정말 js를 처음 접하는 사람을 위해 쉽게쉽게 설명되어서 이해는 잘되지만 넘어가는 부분이 있었는데 노션에서 그런 부분을 보충하기 위한 설명이 잘 되어 있었다. js는 강의를 들은 후에 노션자료를 꼭 참고하여 한번 더 정리 해보는것이 좋을 것 같다.
4.1 오늘 했던 js는 비교적 쉬운 내용이었다고 생각한다. 문자열이나 그것으로 만들어낸 객체들을 이용하는 방법 등은 직관적이고 console에서 바로 확인 할 수 있었기 때문이다. 다만 그동안 배운것들을 그냥 정리만 하고 넘어가지 않고 직접 코드를 입력하며 실습해보자고 결심했기 때문에 간단했던 것에 비해 공부 시간은 좀 더 늘어났다. 앞으로도 다짐을 잊지말자.
4.2 js를 시작하면서 모던자바스크립트deepdive도 같이 보고있다. 인터넷에서 무료로 제공하는거라 빈부분이 있다고는 하는데.. 그건 모르겠고 일단 내가 알던것들을 되게 논리적으로? 정리해주니까 신기하고 재밌다 그냥 대충 이해했는데 이런 원리구나~하는 기분! 또 수업 들을때는 쉽다고 생각했는데 Dom method들이 비슷한 쓰임세지만 자세하게 들여다보면 다르게 동작하는 경우가 많아서 햇갈렸다. innerHtml, innerText, textContent.. 셋다 text를 가져올 수 있지만 다르게 동작한다. 이것들을 이해하는데 초반에 js를 공부하면서 node나 element 등의 개념을 제대로 이해하고 있었던게 도움이 많이 되었다. node는 브라우저에서 html을 dom의 형태로 변환시킬때 만들어지는 하나하나의 요소를 나타낸 '객체'이기 때문에 객체에 포함된 프로퍼티들을 다 살펴 볼 수 있다! 라고 이해하니까 textContent가 왜 그렇게 동작하는지 이해할 수 있었다. innerText는 Element의 node가 아닌 해당 요소만의 속성이기 때문에 하위의 태그에 무엇이 기입되어있는지 까지는 알 수 없다는 것이다. 초반에 이해되지 않았던 개념들을 열심히 읽어둔게 도움이 되는 것 같아서 뿌듯하다. 역시 배워서 버릴 지식은 없나보다!@
4.3 반복문과 조건문을 사용해서 코드를 짜니까 뭔가 재밌음! 아직은 간단한 코드와 과제만 짜서 똑딱똑딱 내 의도대로 움직여주니까 그런거 같음. 슬슬 미뤄둔 밑줄과제들이 많아서 좀 걱정이 되는데.. 이번 주말에는 꼭 해봐야겠음!
4.4 오늘 배운 dom메소드 자체는 배울때나 활용할 때 그렇게 어렵다고 생각하지는 않았다.(예시를 따라해보면 되니까 ㅎ..) 그런데 추가과제로 받은 todolist만들기에서 localstorage에 저장하기에서 그냥 혼쭐이났다 정복하고 말것이다.
4.5 함수를 배우고, 이때까지 했던 dom에 값 추가하기등을 함수형태로 만들어 사용하는 실습을 했다. 사실 간단한 작업을 해서 그런지 함수의 유용함이 그렇게 느껴지지는 않았다. 아마 작업양이 많아지는 프로젝트를 하다보면 함수의 유용함을 느낄 수 있지 않을까? 싶다
4.8 오늘 매니져님께서 행사 진행을 할 때 현재 진도가 빠른편이라는 말을 하셨다. 나는 이전에 js의 앞부분은 혼자 공부 한적이 있어서 지금 진도가 느린편이라고 생각했는데, 새롭게 공부를 시작하는 사람들 입장에서는 이게 빠르게 느껴질수 있겠구나 싶었다. 그러면서 그래도 예전에 내가 엉망이고 실패했다고 생각한 문과식 공부가 아무런 의미가 없지는 않았구나 모든 시간이 결국엔 어떤 형태로든 남게 되는구나 하는 생각을 했다. 사실 개발공부를 하다보면 이게 어떤 자격증이나 성적의 형태로 남는게 아니다보니 눈에 보이는 결과가 없어서 지금보내는 시간이 정말 가치가 있는게 맞을까? 하는 의문이 들 때가 있다. 모든 알 수 없는 미래가 그렇겠지만 그런 불안감이 조금 해소된 기분이었다. 내가 지금 보내는 시간은 낭비가 아니다.
4.9 와 이벤트를 그냥 등록하고 사용할떄는 어렵지 않았는데 버블링 캡쳐링은 정말 어려웠다. 추가 공부가 필요하다. 라이브세션에서 강사님이 알려주셨는데 잠깐 멍때리면 단어를 놓치고 이해를 못했다. 라이브강의 녹화본이 올라오면 다시 한번 봐야겠다!
4.11 점점.. 힘들다..!( ༎ຶŎ༎ຶ ) 배열메소드 객체메소드 생성자함수 타이머메소드 등.. 뭔가 개념을 알면 활용하기 쉬운 단계를 지나서 개념과 활용이 둘 다 어려운 지점을 공부하기 시작하니까 수업을 들으면서도 이해가 잘 안되고 이거 익숙해지고 활용해보려면 실습 많이 해봐야겠다 라는 생각이 든다.(복습만 수업끝나고 두시간반이 걸렸다..) 특히 map filter reduce등은 배우면서도 이거 그냥 반복문으로 하면 안되나? 하는 생각이 계속 들었던걸 보면 익숙해지면 간결하게 배열을 다룰 수 있게 될 메소드들이지만 그러지 못하면 나는 평생 for문만 쓰게될수도 있겠는데? 하는 생각이 들었다. 또 this나 new등은 쉽게 이게 뭐다 하는 식으로 개념만 알고 넘어갔는데 사실 활용에는 문제가 없지만 확실히 공부하지 않아도 되는걸까? 하는 의문도 살짝 들었다.
4.17 후기 써야하는데 스터디 시작된다 바쁘다바뻐 우리네인생
4.18 정말 오늘 우울 최고조였다! 과제도 뜯대로 작동을 안하고 라이브강의에서 비동기에대한 수업을 들었는데 중반부터 이해를 못했더니 그 뒤를 몽땅 멍때리면서 들었다 ㅜㅜ.. 비동기라는 개념은 이해를 하겠는데 그걸 자바스크립트에서 활용하기 위해서 쓴다는 프로미스..? 어싱크 어웨이트..? 정말 어려웠다.. 다시 정리해봐야한다 꼭

profile
시리즈별로 정리중 ✍(´ι _`  )

0개의 댓글