0) Intro

javascript 문법 공부를 위해 Inflearn에 있는 강의를 듣고 정리한 글입니다.

1) 나머지 매개변수와 전개 구문

arguments

  • 함수로 넘어 온 모든 인수에 접근
  • 함수내에서 이용가능한 지역 변수
  • Array 형태의 객체
  • 배열의 내장 메서드가 없음. (forEach, map)
  • arguments.length → arguments의 갯수 반환
  • code
    function showName(name) {
      console.log(arguments.length);
      console.log(arguments[0]);
      console.log(arguments[1]);
    }
    showName("slow", "wave");
    //2
    //slow
    //wave
    

나머지 매개변수(Rest parameters)

  • ES6+부터는 나머지 매개변수 사용을 권장하고 있음.
  • code
    //나머지 매개변수
    function Movie(id, rating, ...tags) {
      this.id = id;
      this.rating = rating;
      this.tags = tags;
    }
    const movie1 = new Movie(1, 5, "fun", "action");
    const movie2 = new Movie(2, 3, "sad", "drama", "good");
    console.log(movie1); //Movie {id: 1, rating: 5, tags: Array(2)}
    console.log(movie2); //Movie {id: 2, rating: 3, tags: Array(3)}
    

전개구문(Spread syntax)

  • code
    let movie = { name: "avatar" };
    let info = { id: 1 };
    let type = ["action", "fantasy"];
    let emotion = ["fun", "exciting"];
    movie = {
      ...movie,
      ...info,
      tags: [...type, ...emotion],
    };
    console.log(movie); //{name: 'avatar', id: 1, tags: Array(4)}
    

2) 클로저(closure)

호이스팅

  • 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미함.
  • 변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮기는 것이라고 할 수 있음.
  • JavaScript는 함수의 코드를 실행하기 전에 함수 선언에 대한 메모리부터 할당 → 함수를 호출하는 코드를 함수 선언보다 앞서 배치할 수 있습니다.

closure

  • 함수와 렉시컬 환경의 조합임.
  • 함수가 생성될 당시의 외부 변수를 기억해서 생성 이후에도 계속 접근 가능함.
  • code
    function makeCounter() {
      let num = 0; //은닉화
    
      return function () {
        return num++;
      };
    }
    
    let counter = makeCounter();
    console.log(counter()); //0
    console.log(counter()); //1
    console.log(counter()); //2
    

3) setTimeout, setInterval, clearTimeout

setTimeout

setInterval, clearTimeut

  • code
    let s = 5;
    
    function countdown() {
      console.log(`5초 카운트다운! ${s--}초`);
      if (s < 0) clearInterval(tId);
    }
    
    const tId = setInterval(countdown, 1000);
    

4) call, apply, bind

  • 함수 호출 방식과 관계없이 this를 지정할 수 있음.

call

  • call 메서드는 모든 함수에서 사용할 수 있으며, this를 특정값으로 지정할 수 있음.
  • code
    const mike = {
      name: "Mike",
    };
    
    function showThisName() {
      console.log(this.name);
    }
    // showThisName(); //TypeError
    showThisName.call(mike); //Mike
    
    function update(birthYear, occupation) {
      this.birthYear = birthYear;
      this.occupation = occupation;
    }
    
    update.call(mike, 1999, "singer");
    console.log(mike); //{name: 'Mike', birthYear: 1999, occupation: 'singer'}
    

apply

  • apply는 함수 매개변수를 처리하는 방법을 제외하면 call과 완전히 같음.
  • call은 일반적인 함수와 마찬가지로 매개변수를 직접 받지만, apply는 매개변수를 배열로 받음.
  • code
    const nums = [4, 2, 1, 2, 10];
    const minNum = Math.min.apply(null, nums); //this가 필요하지 않아서 임의로 null 넣음.
    const maxNum = Math.max.call(null, ...nums);
    console.log(minNum, maxNum); //1 10
    

bind

  • 함수의 this값을 영구히 바꿀 수 있음.
  • code
    const user = {
      name: "mike",
      showName: function () {
        console.log(`hello, ${this.name}`);
      },
    };
    
    user.showName();
    let fn = user.showName;
    fn.call(user);
    fn.apply(user);
    
    let boundFn = fn.bind(user);
    boundFn(); //hello, mike
    

5) 상속, prototype

prototype

  • code
const user = {
  name: "slow",
};

console.log(user.hasOwnProperty("name")); //true
console.log(user.hasOwnProperty("birth")); //false

prototype chain

  • 아래 코드에서 meatPizza와 potatoesPizza에는 공통된 부분이 존재함. (shape, sauce) → 중복된 코드 → prototype chain을 이용해 개선함.
  • code
const meatPizza = {
  shape: "round",
  sauce: "tomato",
  topping: ["meat"],
  time: 10,
};

const potatoesPizza = {
  shape: "round",
  sauce: "tomato",
  topping: ["potatoes"],
  time: 8,
};
  • code
//공통된 부분은 pizza에 넣어줌.
const pizza = {
  shape: "round",
  sauce: "tomato",
};

const meatPizza = {
  topping: ["meat"],
  time: 10,
};
//prototype chain
meatPizza.__proto__ = pizza;
console.log(meatPizza);

console.log(Object.keys(meatPizza)); //["topping",'time"]
console.log(Object.values(meatPizza)); //[["meat"],10]

생성자 함수

  • instance

    • 생성자함수가 새로운 객체 생성할 때 그 객체는 생성자의 인스턴스라고 함.
    • instanceof → 인스턴스인지 확인 가능
  • constructor

    • 생성자로 만들어진 인스턴스 객체의 경우 constructor가 존재함.
    • 프로로타입을 겹쳐 쓰지 않고 하나씩 풀어쓰는 것이 좋은 방법임.
    • 자바스크립트는 명확한 constructor를 보장하지 않음.
  • code (prototype을 하나씩 풀어쓴 경우 → constructor 존재함.)

    const Bmw = function (color) {
      this.color = color;
    };
    
    Bmw.prototype.wheels = 4;
    Bmw.prototype.drive = function () {
      console.log("drive...");
    };
    
    const x5 = new Bmw("red");
    const z4 = new Bmw("blud");
    
    console.log(x5.drive); //drive...
    console.log(x5 instanceof Bmw); //true
    console.log(x5.constructor === Bmw); //true
    
  • code (prototype을 겹쳐서 쓴 경우 → constructor가 존재하지 않음.)

    const Bmw = function (color) {
      this.color = color;
    };
    
    Bmw.prototype = {
      wheels: 4,
      drive() {
        console.log("dirve...");
      },
    };
    
    const x5 = new Bmw("red");
    const z4 = new Bmw("blue");
    
    console.log(x5.drive); //drive...
    console.log(x5 instanceof Bmw); //true
    console.log(x5.constructor === Bmw); //false
    
  • code

    const pizza = function (sauce) {
      this.sauce = sauce;
    };
    
    const p1 = new pizza("tomato");
    p1.sauce = "cream";
    console.log(p1.sauce); //cream으로 변경됨.
    
  • code

    //closure 사용해서 변경되지 않도록 함.
    //초기에 세팅한 값만 얻을 수 있고, 바꿀 수는 없음.
    
    const pizza = function (sauce) {
      const s = sauce;
      this.getSauce = function () {
        console.log(s);
      };
    };
    
    const p2 = new pizza("tomato");
    console.log(p2.getSauce()); //tomato
    

promise

  • callback 함수 - 어떤 일이 완료된 이후에 실행되는 함수임.
  • code
    //성공시 -> resolve, 실패시 -> reject
    const pr = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("ok");
      }, 3000);
    });
    
    pr.then(function (result) {
      //성공시 실행
      console.log(result + "가지러 가자.");
    })
      .catch(function (err) {
        //실패시 실행
        console.log("다시 주문해주세요.");
      })
      .finally(function () {
        //항상 실행
        console.log("주문 끝");
      });
    

async/await

  • code
    const f1 = () => {
      console.log();
      return new Promise((res, rej) => {
        setTimeout(() => {
          res("1번");
        }, 1000);
      });
    };
    
    const f2 = (message) => {
      console.log(message);
      return new Promise((res, rej) => {
        setTimeout(() => {
          res("2번");
        }, 1000);
      });
    };
    
    const f3 = (message) => {
      console.log(message);
      return new Promise((res, rej) => {
        setTimeout(() => {
          res("3번");
        }, 1000);
      });
    };
    
    //프로미스 체이닝
    console.log("시작");
    f1()
      .then((res) => f2(res))
      .then((res) => f3(res))
      .then((res) => console.log(res))
      .catch()
      .finally(() => {
        console.log("끝");
      });
    

참고자료