업데이트:

태그: ,

카테고리:



함수

  • 프로그램을 구성하는 주요 구성요소. 중복 없이 유사한 동작을 하는 코드를 반복 호출


함수 선언문

function name(parameters) {
  ...code...
}
name();
name();
  • function 키워드, 함수이름, 매개변수, 함수 본문으로 이뤄진다.
  • 호출은 함수이름()으로 할 수 있다.


지역 변수

  • 함수 내에서 선언한 변수를 의미.
function showMesage() {
  let message = "test"; // 이 변수는 showMessage함수 내부에서만 사용할 수 있다.
}


외부 변수(전역변수)

  • 함수 내부에서 함수 외부의 변수에 접근하고, 수정할 수 있다.
let message = "test1";
function showMessage() {
  alert(message);
  message = "test2";
  alert(message);
}


  • 외부 변수와 같은 이름의 내부변수가 있다면, 외부변수는 사용되지 않는다.
let message = "test1";
function showMessage() {
  let message = "test2";
  alsert(message);
}


매개변수(인수)

  • 함수 안에 임의의 데이터를 전달.
function showMessage(from, to) {
  alert(from + ":" + to);
}
showMessage("Ann", "hello");
showMessage("Ann", "whats up?");
  • 함수에 매개변수를 전달하면 해당 값이 함수 내부에서 지역변수에 할당된다.
  • 따라서 매개변수의 변경은 함수 외부에 영향을 주지 않는다.
function showMessage(from, text) {
  from = "*" + from + "*"; // "from"을 좀 더 멋지게 꾸며줍니다.

  alert(from + ": " + text);
}

let from = "Ann";

showMessage(from, "Hello"); // *Ann*: Hello

alert(from); // Ann


기본값

  • 매개변수를 지정했으나, 값이 전달되지 않으면 undefined이다.
  • 매개변수가 전달되지 않을때 사용될 기본값을 설정할 수 있다.
function showMessage(from, text = "no text given") {
  alert(from + ":" + text); //text = no text given
}
showMessage("Ann"); //매개변수 1개만 전달


  • JS는 함수를 호출할때마다 함수의 매개변수 기본값을 평가한다.
function showMessage(from, text = anotherfunction()) {
  //anotherfunction은 text가 없을때 호출된다.
}


  • 함수 내부에서 기본값 설정

    • 조건문으로 설정
    function showMessage(from, text) {
      if (text == undefined) {
        text = "빈문자열";
      }
    }
    


  • 논리 연산자로 설정
    function showMessage(from, text) {
      text = text || "빈 문자열";
    }
    


  • nullish 병합 연산자로 설정
    function showMessage(from, text) {
      text = text ?? "빈 문자열";
    }
    


반환 값

  • 함수 호출 시, 특정 값을 반환하게 할 수 있다.

  • return을 만나면 함수는 즉시 중단, 값을 반환한다.
  • return 값이 undefined나 없는 경우엔 undefined를 반환한다.
  • return문 끝에 세미콜론을 자동으로 넣어주므로, 반환값은 괄호로 묶어 사용해야한다.
function showMovie(age) {
  if (!checkAge(age)) {
    return; //undefined
  } else {
    alert("영화 상영");
  }
}


함수 이름짓기

  • 처음 코드를 보더라도, 함수가 어떤 역할을 하는지 확인할 수 있게 하기위함


  • show… : 보여주는 역할
  • get… : 값을 반환
  • calc… : 계산
  • create… : 생성
  • check… : 확인하고 불린값 반환


  • 함수 하나는 동작 하나만 할 수 있어야한다.
  • 독립적인 동작은 다른 함수를 만들어서 호출하도록 해야한다.



함수 표현식

  • 지금까지 표현한 함수는 함수선언식
    function sayHi() {
      alert("Hello");
    }
    


  • 자바스크립트는 함수를 특별한 값으로 취급한다.
  • 이에따라, 변수에 함수를 할당할 수 있다.
  • 이렇게 만드는 함수를 함수표현식이라고 한다.
let sayHi = function () {
  alert("Hello");
};

이렇게 함수가 할당된 변수 sayHi는 함수를 호출할 수도있고, 값을 가진 변수의 역할도 한다.

alert(sayHi); //함수 코드가 보임.
sayHi(); //함수가 실행됨.
let func = sayHi;
func(); //함수가 실행됨


콜백함수

  • 함수를 함수의 인수로 전달하고, 인수로 전달한 그 함수를 나중에 호출하는 것.

    function ask(question, yes, no) {
      if (confirm(question)) yes();
      else no();
    }
    
    function showOk() {
      alert("동의하셨습니다.");
    }
    
    function showCancel() {
      alert("취소 버튼을 누르셨습니다.");
    }
    
    // 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
    ask("동의하십니까?", showOk, showCancel);
    


  • 더 명확하게 선언하려면 익명함수를 사용한다.
  • 익명함수는 ask 바깥에서 접근할 수 없는 함수가된다.

    function ask(question, yes, no) {
      if (confirm(question)) yes();
      else no();
    }
    
    ask(
      "동의하십니까?",
      function () {
        alert("동의하셨습니다.");
      },
      function () {
        alert("취소 버튼을 누르셨습니다.");
      }
    );
    


함수표현식과 함수선언식의 차이

  • 문법
//함수가 독자적인 구문형태로 존재
function sum(a, b) {
  return a + b;
}
//함수가 표현식이나 구문 구성 내부에 생성된다.(한 블럭 아래단계에 있다는 의미)
//할당표현식 let sum =  우측에 존재한다.
let sum = function (a, b) {
  return a + b;
};
  • JS엔진이 함수를 언제 생성하는가

    • 엔진은 스크립트 실행 전, 전역에 선언된 함수 선언문을 찾아 해당 함수를 생성한다.
    • 스크립트는 함수 선언문이 모두 처리된 다음에 실행되므로 스크립트 어디에서는 사용할 수 있다.
    sayHi("John"); // Hello, John
    
    function sayHi(name) {
      //전역공간의 함수
      alert(`Hello, ${name}`);
    }
    
    sayHi("John"); // error!
    let sayHi = function (name) {
      // (\*) 스크립트가 여기까지 실행되어야 함수가 생성됨
      alert(`Hello, ${name}`);
    };
    
  • 스코프

    • 함수선언문이 코드 블록 내에 위치하면 해당 함수는 블록 어디에서든 접근할 수 있다.
    • 블록 외부에선 접근할 수 없다.
    let age = 16;
    if (age < 18) {
      welcome(); //(실행)
    
      function welcome() {
        alert("안녕!");
      }
    
      welcome(); //(실행)
    } else {
      function welcome() {
        alert("안녕하세요!");
      }
    }
    
    welcome(); // Error: welcome is not defined
    
    • 블록 외부에서 함수에 접근하려면 함수 표현식을 사용해야한다.
    let age = prompt("나이를 알려주세요.", 18);
    
    let welcome =
      age < 18
        ? function () {
            alert("안녕!");
          }
        : function () {
            alert("안녕하세요!");
          };
    
    welcome(); // 실행
    



화살표함수

let 함수이름 = (인수1, 인수2, 인수3) => 함수코드;
  • 화살표함수는 함수를 표현하는 또 다른 방식
  • 함수 본문이 1줄인 (리턴값만 명시하는) 함수는 화살표함수가 편하다.
    let mul = (a, b) => a * b;
    


  • 함수가 여러 줄인 경우에, 중괄호 안에 실행할 코드를 넣어주고, 반환값을 명시해야한다.
    let mul = (a, b) => {
      let result = a * b;
      return result;
    };
    



객체

  • 객체 자료형은 자료형에 상관없이 다양한 데이터를 담을 수 있다.
  • 중괄호로 만들고, 키 : 값으로 구성된 프로퍼티를 담는다.

  • 객체 생성은 2가지 방법이 있다.
    let user = new Object(); //객체 생성문법
    let user = {}; //객체 리터럴문법
    


리터럴과 프로퍼티

let user = {
  name: "john",
  age: 30,
};
  • 콜론을 기준으로 키 : 값이다.

  • 키는 프로퍼티 이름, 식별자라고 불린다.

  • 객체의 프로퍼티 값을 읽기 위해선 점 표기법을 사용한다.

    alert(user.name);
    alert(user.age);
    
  • delete연산자로 프로퍼티 삭제 가능.

    delete user.age;
    
  • 프로퍼티 이름에 공백이 들어가면 따옴표로 묶어줘야한다.

    let user = {
      "likes birds": true,
    };
    
  • const로 선언된 객체의 프로퍼티는 수정이 가능하다.

    const user = {
      name: "John",
    };
    user.name = "Anne";
    


대괄호 표기법

공백을 포함한 프로퍼티 키는 점 표기법이 아닌, 대괄호 표기법으로 값을 읽어야한다.

let user = {
  "likes birds": true,
};
alert(user.["likes birds"])


계산된 프로퍼티

  • 프로퍼티 키를 동적으로 할당할 수 있다.
let fruit = prompt("어떤 과일을 구매하시겠습니까?", "apple");

let bag = {
  [fruit]: 5,
};

alert(bag.apple);


단축 프로퍼티

  • 프로퍼티 값을 변수에서 받아와서 할당할 때 사용한다.
function makeUser(name, age) {
  return {
    name, // name: name 과 같음
    age, // age: age 와 같음
    // ...
  };
}


프로퍼티 이름

  • 객체 프로퍼티 키에 특별한 제약이 없다.
  • 단, __proto__는 사용할 수 없다.
  • 프로퍼티 키는 문자열로 자동 형 변환된다.
  • 대괄호 표기법으로 접근하더라도 동일하게 자동형변환된다.
let obj = {
  0: "test", // == "0" : "test"
};
alert(obj["0"]);
alert(obj[0]); //같음


in 연산자

  • 객체는 존재하지 않는 프로퍼티에 접근하면 undefined를 반환한다.
  • in 연산자로 객체에 프로퍼티가 존재여부를 판단할 수 있다.
let user = { name: "John", age: 30 };

alert("age" in user); // user.age가 존재하므로 true가 출력됩니다.
alert("blabla" in user); // user.blabla는 존재하지 않기 때문에 false가 출력됩니다.


for ~ in 반복문

for ~ in 반복문으로 객체의 키를 순회할 수 있다.

for (let key in obj) {
  실행할 코드
}


객체 정렬 방식

  • 객체 프로퍼티에선 정수 프로퍼티는 자동으로 정렬되고, 나머지는 추가한 순서대로 정렬된다.
  • 정수 프로퍼티는 특별한 변형없이 정수에서 왔다 갔다할 수 있는 문자열을 의미한다.(“49”, “12312”, “-1234”, “0” 등…)
let codes = {
  "49": "독일",
  "41": "스위스",
  "44": "영국",
  // ..,
  "1": "미국",
};

for (let code in codes) {
  alert(code); // 1, 41, 44, 49
}

정렬을 막기 위해서, “+49”, “+1” 등으로 프로퍼티 키를 수정하면된다.


참조에 의한 객체 복사

  • 객체를 제외한 원시타입 자료형은 값이 복사되어 할당된다.
  • 객체 그 자체가 아닌, 객체가 저장된 메모리 주소에 대한 참조값이 저장된다.
  • 따라서 다른 변수에 객체를 할당하면, 그 변수를 수정하면 객체도 수정된다.
let user = { name: "John" };

let admin = user;

admin.name = "Pete"; // user.name = "Pete"가 된다.

alert(user.name); //"Pete"


객체간 비교

  • 객체는 참조 값을 가지므로, 같은 객체를 참조하는 변수는 일치, 동등 연산자가 true를 반환한다.
  • 내용이 같더라도, 다른 참조값이라면 false를 반환한다.
let a = {};
let b = a;
let c = {}; // 독립된 두 객체
alert(a == b); //true
alert(a == c); // false


객체 복사

  • 참조값을 복사하는게 아닌, 내용이 같고 독립적인 객체를 만들기 위해선 Object.assign을 사용하면 편하다.

    let user = {
      name: "John",
      age: 30,
    };
    let clone = Object.assign({}, user);
    
  • 단, 중첩 객체인 경우, 객체의 키 값을 복사해오므로, 독립적인 객체가 같은 참조값을 가지는 키를 가지게 되는 경우가 있다.
  • 이를 위해서 깊은 복사를 해야하는데, lodash의 _.cloneDeep 메서드를 사용하거나, 알고리즘을 사용해야한다.



댓글남기기