Giter Club home page Giter Club logo

gmlwjd9405.github.io's People

Contributors

gmlwjd9405 avatar leeyunjea avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

gmlwjd9405.github.io's Issues

Edwith - http

Goal

  • HTTP
  • Request 형식
  • Request Method
  • Response 형식
  • 응답 코드

인터넷(네트워크 통신)의 이해

인터넷이란

  • TCP/IP 기반의 네트워크가 전세계적으로 확대되어 하나의 연결된 네트워크들의 네트워크 (네트워크의 결합체)
  • 인터넷 != WWW(World Wide Web)
    • 인터넷 기반의 대표 서비스 중 하나가 www라고 할 수 있다.
  • 인터넷 기반의 서비스들
이름 프로토콜 포트 기능
www HTTP 80 웹 서비스
Email SMTP/POP3/IMAP 25/110/114 이메일 서비스
FTP FTP 21 파일 전송 서비스
DNS TCP/UDP 53 네임 서비스
NEWS NNTP 119 인터넷 뉴스 서비스
  • 물리적인 하나의 컴퓨터(IP 주소)에는 여러 개의 서버가 동작할 수 있다.
    • 각각의 서버들은 포트라는 값으로 구분돼서 동작한다.

웹의 동작 (HTTP 프로토콜의 이해)

HTTP 란

  • 웹 브라우저와 웹 서버 간의 서로 통신하기 위한 규약
    • 즉, HTTP(Hypertext Transfer Protocol)란 서버와 클라이언트가 인터넷상에서 데이터를 주고받기 위한 프로토콜(protocol)을 말한다.
    • HTTP는 계속 발전하여 HTTP/2까지 버전이 등장한 상태
    • 팀 버너스리(Tim Berners-Lee)와 그가 속한 팀은 CERN에서 HTML뿐만 아니라 웹 브라우저 및 웹 브라우저 관련 기술과 HTTP를 발명하였다.
    • 어떤 종류의 데이터도 전송할 수 있도록 설계되어있다.

HTTP 작동방식

  • HTTP는 서버/클라이언트 모델을 따른다.
    • 클라이언트 -> 요청 -> 서버 -> 응답 -> 클라이언트
    • 장점
      • 불특정 다수를 대상으로 하는 서비스에는 적합하다.
      • 클라이언트와 서버가 계속 연결된 형태가 아니기 때문에 클라이언트와 서버 간의 최대 연결 수보다 훨씬 많은 요청과 응답을 처리할 수 있다.
    • 단점
      • 연결을 끊어버리기 때문에, 클라이언트의 이전 상황을 알 수가 없다.
      • 이러한 특징을 무상태(Stateless)라고 말한다.
      • 이러한 특징 때문에 정보를 유지하기 위해서 Cookie와 같은 기술이 등장하게 되었다.
  • 그림
    • 클라이언트가 원하는 서버에 접속
    • 클라이언트가 서버에 요청
    • 요청에 따른 응답 결과를 다시 클라이언트에 응답
    • 응답이 끝나고 나면 서버와 클라이언트의 연결은 끊긴다.

URL (Uniform Resource Locator)란

  • URL이란
    • 인터넷 상의 자원의 위치
    • 특정 웹 서버의 특정 파일에 접근하기 위한 경로 혹은 주소
  • URL의 표현
  • IP 주소와 포트 번호의 개념
    • IP 주소 또는 도메인 이름
      • 하드웨어 서버(물리적인 컴퓨터)를 찾기 위해 반드시 필요한 정보
      • Ex) 집 주소
    • 포트 번호
      • 해당 물리적인 컴퓨터 안에 존재하는 소프트웨어 서버를 찾기 위한 정보
      • 0보다 큰 숫자로 구성되어 있다.
      • Ex) 집 안의 여러 방 번호

HTTP 속성

  • 요청 메서드: GET, PUT, POST, PUSH, OPTIONS 등
    • 서버에게 요청의 종류를 알려주기 위해 사용
    • 최초의 웹 서버는 GET 방식만 지원
    • 각 메서드의 사용 목적
      • GET: 정보 요청 (SELECT)
      • POST: 정보 밀어넣기 (INSERT)
      • PUT: 정보 업데이트 (UPDATE)
      • DELETE: 정보 삭제 (DELETE)
      • HEAD: (HTTP) 헤더 정보만 요청하는 메서드. 해당 자원이 존재하는지 혹은 서버에 문제가 없는지를 확인
      • OPTIONS: 웹 서버가 지원하는 메서드의 종류를 요청
      • TRACE: 클라이언트의 요청을 그대로 반환하는 메서드. Ex) echo 서비스로 서버 상태를 확인하기 위한 목적으로 주로 사용
  • 요청 URI: 요청하는 자원의 위치를 명시
  • HTTP 프로토콜 버전: 웹 브라우저가 사용하는 프로토콜 버전

tag 정리하기

규칙

  • 소문자 사용
  • 한글/영어 혼용 문제 생각하기
  • 적절한 키워드 설정하기 (가장 큰 범위 먼저 생각)

JS - 함수선언문과 함수표현식의 차이


layout: post
title: '[JavaScript] 함수선언문과 함수표현식의 차이'
subtitle: '자바스크립트의 함수선언문과 함수표현식의 차이에 대해 이해한다.'
date: 2019-04-20
author: heejeong Kwon
cover: '/images/network/http-headers-main.png'
tags: javascript function
comments: true
sitemap :
changefreq : daily
priority : 1.0

Edwith 강의 참고

Goal

  • 자바스크립트의 선언 방식변수의 종류를 확인한다.
    • var과 let, const의 차이에 대해 이해한다.
  • 자바스크립트의 연산자의 종류 및 개념을 이해한다.
  • 자바스크립트의 타입의 종류를 확인한다.
    • 자바스크립트에서 type 체크 방법에 대해 이해한다.
    • 자바스크립트에서 null 체크 방법에 대해 이해한다.

함수

  • 함수는 여러 개의 인자를 받아서, 그 결과를 출력한다.
  • 파라미터의 개수와 인자의 개수가 일치하지 않아도 오류가 나지 않는다.
    • 만약, 파라미터 1개가 정의된 함수를 부를 때, 인자의 개수를 0개만 넣어 실행하면 이미 정의된 파라미터(매개변수)는 undefined이라는 값을 갖게 된다.
    • 이는 변수는 초기화됐지만, 값이 할당되지 않았기 때문이다.
  • Ex.
// 함수의 호출.
function printName(firstname) {
    var myname = "HEEE";
    return myname + " " +  firstname;
}

반환값과 undefined

  • 함수는 어떤 타입의 값이라도 반환할 수 있다.
  • 자바스크립트 함수는 반드시 return값이 존재하며, 없을 때는 기본 반환값인 'undefined'가 반환된다.
    • 자바스크립트에서는 void 타입이 없다.
  • Ex. 반환값: undefined
function printName(firstname) {
    var myname = "HEEE";
    var result = myname + " " +  firstname;
}
  • 자바스크립트에서는 함수도 객체이다.

    • 따라서 다른 객체와 마찬가지로 넘기거나 할당할 수 있다.
  • TIP 함수 호출 vs 함수 참조

    • 함수 호출
      • 함수 식별자 뒤에 괄호를 쓰면 함수 바디를 실행한다
      • 함수를 호출한 표현식은 반환값이 된다.
      • testFunc() // test!! (함수 호출)
    • 함수 참조
      • 함수 식별자 뒤에 괄호를 쓰지 않으면 함수는 실행되지 않는다.
      • testFunc // function testFunc() // (함수 참조)
      • const f = testFunc 함수를 변수에 할당하면 f()과 같이 다른이름으로 함수를 호출할 수 있다.
  • 함수를 객체 프로퍼티에 할당할 수도 있다.

const o = {}
o.f = testFunc
o.f() // test!!
  • 함수를 객체 배열 요소로 할당할 수도 있다.
const arr = [1, 2, 3]
arr[1] = testFunc
arr[1]() // test!!
  • 함수를 호출하면 함수 매개변수는 변수 자체가 아니라 그 값을 전달받는다.
    • 따라서 넘겨받은 원시 값 매개변수를 함수 내에서 변경하더라도 밖에서는 변경되지 않는다.
    • 하지만 넘겨받은 매개변수가 객체이고, 이 객체 자체를 변경하면, 그 객체는 함수 밖에서도 바뀐 점이 반영된다.
  • TIP 원시 값과 객체의 차이
    • 원시 값은 불변이므로 수정할 수 없다.
    • 원시 값을 담은 변수는 수정할 수 있지만(다른 값으로 바꿀 수 있지만) 원시 값 자체는 바뀌지 않는다.
    • 반면 객체는 바뀔 수 있다.

함수선언문과 함수표현식

함수선언문

// 함수의 호출.
function printName(firstname) {
    var myname = "HEEE";
    return myname + " " +  firstname;
}

함수표현식 (Function Expression)

  • 변수값에 함수 표현을 담아 놓은 형태
  • 함수표현식은 익명 함수표현식과 기명 함수표현식으로 나눌 수 있다.
    • 일반적으로 함수표현식이라고 부르면 앞에 익명이 생략된 형태라고 볼 수 있다.
    • 익명 함수표현식: 함수에 식별자가 주어지지 않는다.
    • 기명 함수표현식: 함수의 식별자가 존재한다.
var test1 = function() { // (익명) 함수표현식
  return '익명 함수표현식';
}

var test2 = function test2() { // 기명 함수표현식 
  return '기명 함수표현식';
}
  • 함수선언문과 달리 선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있다.
/* 정상 */
function printName(firstname) { // 함수선언문
    var inner = function() { // 함수표현식
        return "inner value";
    }
    
    var result = inner();
    console.log("name is " + result);
}

printName(); // "name is inner value"
/* 오류 */
function printName(firstname) { // 함수선언문
    console.log(inner); // "undefined": 선언은 되어 있지만 값이 할당되어있지 않은 경우
    var result = inner(); // ERROR!!
    console.log("name is " + result);

    var inner = function() { // 함수표현식 
        return "inner value";
    }
}
printName(); // TypeError: inner is not a function

/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */
/* 오류 */
function printName(firstname) { // 함수선언문
    var inner; // Hoisting - 변수값을 끌어올린다. (선언은 되어 있지만 값이 할당되어있지 않은 경우)
    console.log(inner); // "undefined"
    var result = inner(); // ERROR!!
    console.log("name is " + result);

    inner = function() { // 함수표현식 
        return "inner value";
    }
}
printName(); // TypeError: inner is not a function
  • Q. "printName이 is not defined" 이라고 오류가 나오지 않고, function이 아니라는 TypeError가 나오는 이유?

  • A. printName이 실행되는 순간 (Hoisting에 의해) inner는 'undefined'으로 지정되기 때문

  • inner가 undefined라는 것은 즉, 아직은 함수로 인식이 되지 않고 있다는 것을 의미한다.

  • 함수표현식보다 함수선언문을 더 자주 사용하지만, 어떤 코딩컨벤션에서는 함수표현식을 권장하기도 한다.

    • 즉, 어떤 컨벤션을 갖던지 한가지만 정해서 사용하는 게 좋다.

호이스팅(Hoisting)이란

  • 호이스팅(Hoisting)이란
    • 함수 안에 있는 변수들을 모두 끌어올려서 선언하는 것을 말한다.
  • 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 미리 다 모아서 선언한다.
    • 자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.
    • 함수 안에 존재하는 변수/함수선언에 대한 정보를 기억하고 있다가 실행시킨다.
    • 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다. (실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것)
/* 정상 */
function printName(firstname) { // 함수선언문 
    var result = inner();
    console.log(typeof inner); // "function"
    console.log("name is " + result);

    function inner() { // 함수선언문 
        return "inner value";
    }
}

printName(); // "name is inner value"

/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */
/* 정상 */
function printName(firstname) { // 함수선언문 
    function inner() { // Hoisting - 함수선언을 끌어올린다.
        return "inner value";
    }

    var result = inner();
    console.log(typeof inner); // "function"
    console.log("name is " + result);
}

printName(); // "name is inner value"
  • 즉, 해당 예제에서는 함수선언문이 아래에 있어도 printName 함수 내에서 inner를 function으로 인식하기 때문에 오류가 발생하지 않는다.

- arguments 객체

함수가 실행되면 그 안에는 arguments라는 특별한 지역변수가 자동으로 생성됩니다.

arguments의 타입은 객체 입니다.(console.log( typeof arguments) 로 확인해보세요!)

자바스크립트 함수는 선언한 파라미터보다 더 많은 인자를 보낼 수도 있습니다.

이때 넘어온 인자를 arguments로 배열의 형태로 하나씩 접근할 수가 있습니다.

arguments는 배열타입은 아닙니다.

따라서 배열의 메서드를 사용할 수가 없습니다.

function a() {
console.log(arguments);
}
a(1,2,3);
자바스크립트의 가변인자를 받아서 처리하는 함수를 만들때 등에서 arguments속성을 유용하게 사용할 수가 있습니다.

응용해보기

arguments속성을 사용해서 , 1~무한대까지 인자를 받아 합을 구하는 함수를 만들어봅시다.

생각해보기

arrow function
ES2015에는 arrow function이 추가됐다.

arrow function 참고 바로가기

간단하게 함수를 선언할 수 있는 문법으로 처음에는 꽤 낯설수 있습니다.

하지만 점점 많이 사용되고 있는 syntax이므로 같이 알아두어도 좋을 것 같습니다.

function getName(name) {
return "Kim " + name ;
}

//위 함수는 아래 arrow함수와 같다.
var getName = (name) => "Kim " + name;

호이스팅

  • 변수/함수 '선언'과 밀접한 관련이 있다.

  • JS 엔진을 코드를 실행하기 전에 코드 전반에 걸쳐서 선언된 내용이 있는지 쭉 훑어보고 발견하는 족족 위로 끌어올린다.

  • var로 선언한 변수 / 함수는 선언만 끌어올려진다는 것이며, 할당은 끌어올려지지 않는다.

    • 하지만 변수에 할당된 함수 표현식은 끌어올려지지 않는다.
    • 따라서 이때는 변수의 스코프 규칙을 그대로 따른다.
    • 해당 함수는 정의되지 않았다는 에러가 뜬다.
  • var를 쓰면 혼란스럽고 쓸모없는 코드가 생길 수 있다. 그럼 왜 var와 호이스팅을 이해해야 할까?

    • ES6를 어디에서든 쓸 수 있으려면 아직 시간이 더 필요하므로 ES5로 트랜스컴파일을 해야한다.
    • 따라서 아직은 var가 어떻게 동작하는지 이해하고 있어야 한다.

화살표 함수

  • 화살표 함수 (Arrow Function, Fat Arrow)
    • 함수를 정의할 때 function이라는 키워드를 사용하지 않고 =>로 대체
    • 흔히 사용하는 콜백 함수의 문법을 간결화
    // ES5 함수 정의 방식 (function expression)
    var sum = function (a, b) {
        return a + b;
    };
    
    // ES6 함수 정의 방식
    var sum = (a, b) => {
        return a + b;
    }
    sum (10, 20);
    /* 화살표 함수 사용 예시 */
    
    var arr = ["a", "b", "c"];
    // ES5
    arr.forEach(function(value){ // 익명 함수
        console.log(value); // a, b, c
    });
    // ES6
    arr.forEach(value => console.log(value)); // a, b, c
  • 향상된 객체 리터럴 (Enhanced Object Literals)
    • 객체의 속성을 메서드로 사용할 때 function예약어를 생략하고 생성 가능
    // 객체 
    var dictionary = {
        words: 100, 
        /* 속성 메서드: 속성에 function을 연결 */
        // ES5
        lookup: function() {
            console.log("find words");
        },
        // ES6 - ': funtion' 생략 
        lookup() {
            console.log("find words");
        }
    };
    • 객체의 속성명과 값 명이 동일할 때 아래와 같이 축약 가능
    var figures = 10;
    var dictionary = {
        // figures: figures,
        figures
    };

자바스크립트의 버전

  • 자바스크립트 버전은 ECMAScript(줄여서 ES, 이크마스크립트)의 버전에 따라서 결정되고, 이를 자바스크립트 실행 엔진이 반영한다.
    • 자바스크립트 엔진은 작성한 JS 코드를 한 줄씩 해석하면서 실행을 준비한다.
  • ES5, ES6(ES2015).. 이런 식으로 버전을 일컫는다.
  • 2018년을 중심으로 ES6를 지원하는 브라우저가 많아서 몇 년간 ES6 문법이 표준으로 쓰이고 있다.
  • ES6는 ES5문법을 포함하고 있어 하위호환성 문제가 없다.
    • 다만 feature별로 지원하지 않는 브라우저가 있을 수 있어 주의해야 한다.
  • Bable
    • 구 버전 브라우저 중에서는 ES6의 기능을 지원하지 않는 브라우저가 있으므로 transpiling이 필요
    • ES6의 문법을 각 브라우저의 호환 가능한 ES5로 변환하는 컴파일러
    • Babel 온라인 에디터: https://babeljs.io/repl/

변수

  • 변수는 var, let, const로 선언할 수 있다.
  • 어떤 것을 사용하는가에 의해서 scope, 즉 변수의 유효범위가 달라진다.
  • ES6 이전 버전에서는 var를 사용해서 변수를 선언할 수 있다.
    • var로 선언한 변수는 끌어올린다는 뜻의 호이스팅(hoisting) 이라는 매커니즘을 따른다.
var a = 2;
var a = "aaa";
var a = 'aaa';
var a = true;
var a = [];
var a = {};
var a = undefined;

변수의 Scope

  • {}에 상관없이 스코프가 설정된다.
var sum = 0;
for(var i = 1; i <= 5; i++) {
    sum = sum + i;
}
console.log(sum); // 15
console.log(i); // 6

ES6 새로운 변수 선언 방식 - const, let

  • 블록 단위 {}로 변수의 범위가 제한되었다.
    let sum = 0;
    for (let i=1; i<=5; i++) {
        sum = sum + i;
    }
    console.log(sum); // 10
    console.log(i); // Uncaught ReferenceError: i is not defined
  • const: 한번 선언한 값에 대해서 변경할 수 없다.(상수 개념)
    /* 예시 */
    const a = 10;
    a = 20; // Uncaught TypeError: Assignment to constant variable
    
    /* [주의!] 하지만, 객체나 배열의 내부는 변경할 수 있다. */
    const a = {};
    a.num = 10;
    console.log(a); // {num: 10}
    
    const b = [];
    b.push(20);
    console.log(b); // [20]
  • let: 한번 선언한 값에 대해서 다시 선언할 수 없다. 변경은 가능
    • 메모리에 할당하면 다시 할당하지 못함
  • 간단한 scope 예시
    function f() {
        {
          let x;
          {
              // 새로운 블록 안에 새로운 x의 스코프가 생김
              const x = "sneaky";
              x = "foo"; // 위에 이미 const로 x를 선언했으므로 다시 값을 대입하면 Error
          }
          // 이전 블록 범위로 돌아왔기 때문에 'let x'에 해당하는 메모리에 값을 대입
          x = "bar";
          let x = "inner"; // SyntaxError: Identifier 'x' has already been declared
        }
    }

연산자

  • 연산자 우선순위를 표현하기 위해서는 ()를 사용하면 된다.
  • 수학 연산자, 논리 연산자, 관계 연산자, 삼항 연산자 등이 있다.

수학 연산자

  • +, -, *, /, %(나머지) 등이 있다.

논리 연산자

  • && 연산자
    • 모든 값이 true인지 확인하지만, 첫 번째가 이미 false라면 그 이후의 값은 확인하지 않는다.
    • 모든 값이 true인 경우 마지막 값이 할당된다.
  • || 연산자
    • 첫 번째가 true인 경우 그 이후의 값은 확인하지 않고 첫 번째 값이 할당된다.
// or 연산자 활용
const name = "myname";
const result = name || "default";
console.log(result); // myname 
const result2 = name && "test";
console.log(result2); // test (&&의 경우, 뒤의 값이 할당된다.)

var name = "";
var result = name || "default";
console.log(result); // default 

삼항 연산자

  • 간단한 비교와 값 할당은 삼항연산자를 사용할 수 있다.
const data = 11;
const result = (data > 10) ? "ok" : "fail";
console.log(result); // ok 

비교 연산자

  • 비교는 == 보다는 === 를 사용한다.

    • ===의 경우는 Type까지 확인하는 연산자이다.
    • ==의 경우 임의적으로 Type을 바꿔서 비교하기 때문에 원하는 결과와 다른 값이 나올 수 있다.
  • ==로 인한 다양한 오류 상황 예시

    0 == false; // true
    "" == false; // true 
    null == false; // false (null은 객체)
    undefined == false; // false 
    0 == "0"; // true
    null == undefined; // true 
  • TIP 자바스크립트의 null 체크에서의 ! 사용 시 주의

    • 0, null, undefined, "", {}, []
      var target;
      
      target = 0;
      console.log(!target); // true
      target = null;
      console.log(!target); // true
      target = undefined;
      console.log(!target); // true
      target = "";
      console.log(!target); // true
      target = {};
      console.log(!target); // false
      target = [];
      console.log(!target); // false 

자바스크립트의 타입

  • undefined, null, boolean, number, string, object, function, array, Date, RegExp 등

기본형과 참조형의 종류

  • Primitive
    • Number
    • String
    • Boolean
    • null
    • undefined
  • Reference: 기본형 데이터의 집합이라고 할 수 있다.
    • Object
      • Array
      • Function
      • RegExp

기본형과 참조형의 차이점

  • 기본형: 값을 그대로 할당
  • 참조형: 값이 저장된 주소값을 할당(참조)

자바스크립트 Type 체크

  • 컴파일 단계가 없는 JavaScript의 Type은 선언할 때가 아니고, 실행 타임 (Dynamic Type)에 결정된다.
    • 함수 안에서의 파라미터나 변수는 실행될 때 그 타입이 결정된다.
  • 타입을 체크하는 또렷한 방법은 없다.
    • 정확하게는 toString.call() 함수를 이용해서 그 결과를 매칭하곤 하는데, 문자, 숫자와 같은 자바스크립트 기본 타입은 typeof 키워드를 사용해서 체크할 수 있습니다.
    • 배열은 타입을 체크하는 isArray함수가 표준으로 생겼다. (IE와 같은 구 브라우저를 사용해야 한다면 지원범위를 살펴보고 사용)
  • 예시
    toString.call("test"); // "[object String]"
    
    const target = "test";
    typeof target; // "string"

관련된 Post

Reference

Linux(Centos7) 환경에서의 폰트

Linux환경에서 WenQuanYi Micro Hei 폰트가 깨지는 것 같습니다.

이미지 첨부하였습니다.

블로그 많이 참고하고있어요! 감사합니다 :D

스크린샷, 2019-05-30 12-09-26

미완성글 저장하기

변수 선언 방식
반복문과 조건문
데이터 타입별 기본적인 메소드들
형변환 및 연산자, 표현식 등


화살표 표기법

  • function이라는 단어와 중괄호 숫자를 줄이려고 고안된 단축 문법
  • 화살표 함수는 항상 익명이다.
    • 화살표 함수도 변수에 할당할 수는 있지만, function 키워드처럼 이름 붙은 함수를 만들 수는 없다.
  • 세 가지 단축 문법
  1. function을 생략해도 된다.
  2. 함수에 매개변수가 단 하나 뿐이라면 괄호(())도 생략할 수 있다.
  3. 함수 바디가 표현식 하나라면 중괄호와 return문도 생략할 수 있다.
  • 예시
const f1 = function() { return 'hello' }
// 또는
const f1 = () => 'hello'
const f2 = function(name) { return 'hello, ${name}' }
// 또는
const f2 = name => 'hello, ${name}'
const f3 = function(a, b) { return a + b }
// 또는
const f3 = (a, b) => a + b
  • 화살표 함수는 익명함수를 만들어 다른 곳에 전달하려 할 때 가장 유용하다.
  • 일반적인 함수와 몇가지 중요한 차이점
    1. this가 다른 변수와 마찬가지로, 정적으로 묶인다.
    2. 화살표 함수는 객체 생성자로 사용할 수 없고, arguments 변수도 사용할 수 없다. (하지만 ES6에서 확산 연산자가 생겨 arguments 변수는 필요 없다.)

함수스코프, 실행컨텍스트

스코프: 유효범위(변수)

  • 함수가 정의될 때

  • 변수와 상수, 매개변수가 언제 어디서 정의되는지 결정하는 것을 말한다.

  • 스코프 vs 존재

    • 스코프
      • 가시성(visibility)이라고도 부르며, 프로그램의 현재 실행 중인 부분, 즉 실행 컨텍스트(execution context)에서 현재 보이고 접근할 수 있는 식별자들을 말한다.
    • 존재
      • 존재한다는 말은 그 식별자가 메모리가 할당된(예약된) 무언가를 가리키고 있다는 뜻이다.
    • 무언가가 더는 존재하지 않는다고 해도 자바스크립트는 메모리를 바로 회수하지 않는다.
    • 그것을 계속 유지할 필요가 없다고 표시해 두면, 주기적으로 일어나는 가비지 콜렉션 프로세스에서 메모리를 회수한다.
  • 정적 스코프

    • 어떤 변수가 함수 스코프 안에 있는지 함수를 정의할 때 알 수 있다는 것을 의미한다.
    • 즉, 함수를 호출할 때 알 수 있는 것이 아니다.
    • 자바스크립트의 정적 스코프는 전역(global) 스코프와 블록(block) 스코프, 함수(function) 스코프에 적용된다.
  • 전역 스코프

    • 스코프는 계층적이며 트리의 맨 아래에는 바탕이 되는 무언가가 있어야 한다.
    • 전역 스코프는 프로그램을 시작할 때 암시적으로 주어지는 스코프를 의미한다.
    • 자바스크립트 프로그램을 시작할 때, 즉 어떤 함수도 호출하지 않았을 때 실행 흐름은 전역 스코프에 있다.
    • 전역 스코프에서 선언한 것은 무엇이든 프로그램의 모든 스코프에서 볼 수 있다.
  • 블록 스코프

    • let과 const는 식별자를 블록 스코프에서 선언한다.
    • 블록 스코프는 그 블록의 스코프에서만 보이는 식별자를 의미한다.

실행 컨텍스트: 실행되는 코드덩어리(추상적 개념)

  • 함수가 실행될 때
  • 호이스팅 후의 코드 본문 내용, this 바인딩 등의 정보가 담긴다.
  • 사용자가 함수를 호출했을 때 내부적으로 해당 함수를 실행하기 위해 필요한 정보들을 불러 모아놓은 하나의 집합체
var a = 1;
function outer() {
  console.log(a); // 1. 1

  function inner() { 
    console.log(a); // 2. undefined
    var a = 3;
  }
  inner();
  console.log(a); // 3. 1
}
outer();
console.log(a); // 4. 1

메소드

  • 함수처럼 생겼는데 .이 붙은 것

  • 함수와 메소드의 차이점

    • this를 바인딩하는지에 따라
    • 메소드는 this를 바인딩한다.
    • . 앞에까지가 this
  • 객체의 프로퍼티인 함수를 메서드라고 불러 일반적인 함수와 구별한다.

  • 예시

const o = {
  name: 'Wallace', // 원시 값 프로퍼티
  bark: function() {
    return 'Woof!' // [방법1] 함수 프로퍼티(메서드) 
  }
  bark2() {
    return 'Woof?' // [방법2] ES6 문법 - 함수 프로퍼티(메서드)
  }
} 

콜백함수

  • something will call this function back(sometime somehow)

  • 제어권을 넘겨준다. 맡긴다.

  • 콜백함수를 어떻게 처리할지는 넘겨받은 대상이 결정한다.

  • 예시 1

// MDN 정의
setInterval(callback, milliseconds)
setInterval(function () {
    console.log('1초마다 실행될 겁니다.');
}, 1000);
  • 주기함수 setInterval 호출. 인자1: 콜백함수, 인자2: 주기(ms)

  • 1초마다 1번씩 자동으로 콜백함수를 부른다.

  • 즉, 콜백함수에 대한 제어권을 setInterval에게 넘긴 것이다.

  • 예시 2

// MDN 정의
arr.forEach(callback[, thisArg])
/*
currentValue: 배열에서 현재 처리 중인 요소.
index: 배열에서 현재 처리 중인 요소의 인덱스.
array: forEach()가 적용되고 있는 배열.
*/

// 같은 동작을 하도록 직접 구현
Array.prototype.forEach = function(callback, thisArg) {
    var self = thisArg || this; // thisArg가 없으면 Array의 인스턴스 
    for(var i = 0; i < this.length; i++) {
        callback.call(self, this[i], i, this); // this 바인딩의 핵심. value, index, array
    } // callback에 어떤 데이터를 매개변수로 넘겨줄지 정해져 있다.
}
var arr = [1, 2, 3, 4, 5];
var entried = [];
arr.forEach(function(v, i) {
    entries.push([i, v, this[i]]);
}, [10, 20, 30, 40, 50]);

console.log(entries);
  • 반복함수 forEach 호출. 인자1: 콜백함수, 인자2: this로 인식할 대상(생략가능)

  • 콜백함수에 대한 제어권을 forEach에 넘겼다.

  • 결과: [ [0, 1, 10], [1, 2, 20], [2, 3, 30], [3, 4, 40], [4, 5, 50], ]

  • 예시 3

var arr = [1, 2, 3, 4, 5];
// 첫 번째 인자는 index를, 두 번째 인자는 value를 받고 싶다고 하자.
arr.forEach(function(index, value) {
    console.log(index, value); 
});
  • 하지만! 정의되어 있는 forEach에 의해 실제 출력 결과는 value, index 순으로 들어간다.

  • 즉, 콜백함수를 정의할 때 파라미터의 순서는 제어권을 넘겨받을 대상(여기서는 forEach)의 규칙을 반드시 따라야 한다.

  • 예시 4 - 이벤트 핸들러

document.body.innerHTML = '<div id="a">abc</div>';
function cbFunc(x) {
    console.log(this, x);
}
document.getElementById('a').addEventListener('click', cbFunc);

$('#a').on('click', cbFunc); // JQuery
  • 예상: this는 바인딩한 것이 없으니 global 객체, x로는 넘긴 것이 없다.
  • 결과: <div id="a">abc</div> => MouseEvent {isTrusted: true, screenX: 11, ...
  • addEventListener의 규칙과 다르게 콜백함을수를 정의했기 때문에 this와 x 모두 잘못 출력되었다.
  • 규칙 => 첫 번째 인자: 이벤트 객체, 두 번째 인자: 이벤트 타겟
// MDN 정의
target.addEventListener(type, listener[, useCapture]);
/*
type: 등록할 event type을 나타내는 문자열
listener: 특정 타입의 이벤트가 발생할 때 알림을 받을 객체. 
*/
  • 콜백함수의 특징
    • 다른 함수(A)의 매개변수로 콜백함수(B)를 전달하면, A가 B의 제어권을 갖게 된다.
    • 위의 예에서
      • A: setInterval, forEach, addEventListener
    • 특별한 요청(bind)이 없는 한 A에 미리 정해진 방식에 따라 B를 호출한다.
    • 미리 정해진 방식이란
      • this에 무엇을 바인딩할지
      • 매개변수에는 어떤 값들을 지정할지
      • 어떤 타이밍에 콜백을 호출할지 등
    • 주의! 콜백은 매소드가 아닌 함수!!
var arr = [1, 2, 3, 4, 5];
var obj = {
  vals: [1, 2, 3],
  logValues: function(v, i) {
    if(this.vals) {
      console.log(this.vals, v, i);
    } else {
      console.log(this, v, i);
    }
  }
};
obj.logValues(1, 2); // 1. 
arr.forEach(obj.logValues); // 2.  
  1. obj.logValues(1, 2);
  • 메소드로 호출. 즉, this가 obj가 된다.
  • if(this.vals)가 참이므로, 아래 log가 출력된다.
  • 결과: {_vals: Array{3}, logValues: f} 1 2
  1. arr.forEach(obj.logValues);
  • 콜백함수로 전달. 즉, obj.logValues가 가리키는 참조가 넘어간다.
  • this가 forEach의 규칙을 따른다.
  • this가 바인딩되지 않았기 때문에 Window가 출력된다.
  • 결과: Window {stop: f, open: f, alert: f, confirm: f, prompt: f, ...} 1 0

this 키워드

  • 일반적으로 this는 객체의 프로퍼티인 함수에서 의미가 있다.
  • 메서드를 호출하면 this는 호출한 메서드를 소유하는 객체가 된다.
  • 예시
const o = {
  name: 'doy',
  speak() {
    return 'My name is ${this.name}',
  }
}
  • o.speak()를 호출하면 this는 o에 묶인다.
  • this는 함수를 어떻게 선언했느냐가 아니라 어떻게 호출했는냐에 따라 달라진다.
  • 즉, this가 o에 묶인 이유는 speak가 o의 프로퍼티여서가 아니라, o에서 speak를 호출했기 때문이다.
const speak = o.speak
speak === o.speak // true, 두 변수는 같은 함수를 가리킨다.
speak() // 'My name is undefined!'
  • 함수를 이렇게 호출하면 자바스크립트는 이 함수가 어디에 속하는지 알 수 없으므로 this는 undefined에 묶인다.

  • 중첩된 함수 안에서 this를 사용하려다보면 혼란스러울 때가 많다.

const o = {
   name: 'doy',
   greetBackwards: function() {
       // 추가
       const self = this
       function getReverseName() {
           let nameBackwards = ''
           for(let i=this.name.length-1; i>=0; i--) {
               // nameBackwards += this.name[i]
               // 아래로 변경
               nameBackwards += self.name[i]
           }
           return nameBackwards
       }
       return `${getReverseName()} si eman ym ,olleH`
   },
}
o.greetBackwards()
  • 다른 변수에 this를 할당하여 이런 문제를 해결한다.
  • 또는 화살표 함수를 이용하며 이런 문제를 해결할 수도 있다.
const o = {
   name: 'doy',
   greetBackwards: function() {
       const getReverseName = () => {
         let nameBackwards = ''
         for(let i=this.name.length-1; i>=0; i--) {
           nameBackwards += this.name[i]
         }
         return nameBackwards
       }
       return `${getReverseName()} si eman ym ,olleH`
   },
}
o.greetBackwards()
  1. 전역공간에서: 전역 객체. window/global: 전역 객체의 구현체
  • 브라우저 콘솔에서 console.log(this);는 window
  • node.js에서 console.log(this);는 global
  1. 함수 내부에서: 전역 객체. window/global
  • default가 전역 객체
  • 변경될 수 있다.
  1. 메소드 호출시
  • 메소드를 호출한 주체 (메소드명 앞)
// Ex 1) a객체 
var a = {
  b: function() {
    console.log(this);
  }
}
a.b();
// Ex 2) a.b객체
var a = {
  b: {
    c: function() {
      console.log(this);
    }
  }
}
a.b.c();
  • 함수는 (전역객체의) 메소드다! (라고 생각하자)
    • 앞에 뭐가 있으면 걔가 this
    • 그렇지 않으면 전역객체가 this
    • window. / global. 이 생략되었다고 본다.
  • 내부 함수에서의 우회법
var a = 10;
var obj = {
  a: 20,
  b: function() { // b는 메서드, c는 함수 
    console.log(this.a); // 20

    function c() {
      console.log(this.a); // 10
    }
    c();
  }
}
obj.b();
  • 내부 함수에서도 this를 쓸 수 있는 방법? Scope Chain 이용
  • 자신의 Scope에서 찾다가 없으면 위로 올라간다.
var a = 10;
var obj = {
  a: 20,
  b: function() { // b는 메서드, c는 함수 
    var self = this;
    console.log(this.a); // 20

    function c() {
      console.log(self.a); // 20
    }
    c();
  }
}
obj.b();
  1. callback에서
  • 기본적으로는 함수내부에서와 동일
  • 제어권을 가진 함수가 callback의 this를 명시한 경우 그에 따른다.
  • 개발자가 this를 바인딩한 채로 callback을 넘기면 그에 따른다.
var callback = function() {
  console.dir(this); 
};
var obj = {
  a: 1, 
  b: function(cb) {
    cb(); // 결과: window

    cb.call(this); // 결과: Object i a: 1 b: function(cb)...
    // 제어권을 넘겨받은 함수나 메서드가 this를 다른 것으로 명시하면, 다른 객체 출력 
  }
};
obj.b(callback);
var callback = function() {
  console.dir(this); 
};
var obj = {
  a: 1 
};

setTimeout(callback, 100); // 결과: window

setTimeout(callback.bind(obj), 100); // 결과: Object
  1. 생성자 함수에서
  • 인스턴스
function Person(n, a) {
  this.name = n;
  this.age = a;
}
var gomugom = new Person('고무곰', 30);
console.log(gomugom) 

call, apply, bind

  • 자바스크립트에서는 함수를 어디서, 어떻게 호출했느냐와 관계없이 this가 무엇인지 지정할 수 있다.
func.call(thisArg[, arg1[, arg2[, ...]]]) // 즉시 호출
func.apply(thisArg, [argsArray]) // 즉시 호출 (배열 요소를 함수 매개변수로 사용해야 할 때 유용)
func.bind(thisArg[, arg1[, arg2[, ...]]]) // 새로운 함수 생성(currying), 호출 X
  • 첫 번째 매개변수는 this로 사용할 값이고, 뒤어 이어지는 매개변수는 호출하는 함수로 전달된다.
function a(x, y, z) {
  console.log(this, x, y, z);
}
var b = {
  c: 'eee'
};

a.call(b, 1, 2, 3);

a.apply(b, [1, 2, 3]);

var c = a.bind(b);
c(1, 2, 3);

var d = a.bind(b, 1, 2);
d(3);
  • 모두 출력 결과는 Object {c: "eee"} 1 2 3으로 동일
  • call

  • apply
    • call과 동일
    • 배열 요소를 함수 매개변수로 사용해야 할 때 유용
  • bind
    • 함수의 this 값을 영구적으로 바꿀 수 있다.
    • bind는 함수의 동작을 영구적으로 바꾸기때문에 찾기 어려운 버그의 원인이 될 수 있다.
    • bind는 매우 유용하지만, 함수의 this가 어디에 묶이는지 정확히 하악하고 사용해야 한다.

클로저

클로저

A closer is the combination of a function 
and the lexical environment(사전적 환경) which that function was declared.
=> 함수와 함수가 선언된 어휘적 환경의 조합이다.??

선언 당시의 환경에 대한 정보를 담은 객체 (구성 환경)

  • 함수와 그 함수가 선언될 당시의 환경정보 사이의 조합
  • Scope와 밀접한 관계가 있다.
  • Scope는 변수의 유효범위. Closer는 유효범위에 의한 현상/상태
  • 즉, 함수 내부에서 생성한 데이터와 그 유효범위로 인해 발생하는 특수한 현상/상태
  • 닫혀있음. 폐쇄성, 완결성
    • 따라서 클로저에서 외부에 정보를 제공할 수 있는 유일한 수단은 해당 정보를 return하는 것이다.
    • return function이어도 변하지 않는 것이 있다.
    • 최초 선언시의 scope 및 lexical environment는 변하지 않는다.
  • 최초 선언시의 정보를 유지
  1. 접근 권한 제어
function a() {
  var x = 1;
  function b() {
    console.log(x);
  }
  b();
}
a();
console.log(x);
  • x에 대한 접근 권한은 function a와 b 내부에서는 가능
  • 그 외부에서는 불가능
  1. 지역변수 보호

  2. 데이터 보존 및 활용

function a() {
  var x = 1;
  return function b() {
    console.log(x);
  }
}
var c = a();
c(); // x의 값을 출력. 하지만 변경은 불가.
  • 외부에 권한 부여
  • getter, setter를 이용
  • _x는 외부에 전혀 노출되어 있지 않다.
function a() {
  var _x = 1;
  return function b() {
    get x() { return _x; },
    set x(v) { _x = v; }
  }
}
var c = a();
c.x = 10; // 외부에서 x 프로퍼티 변경 가능.
  • 예시
function setName(name) {
  return function() {
    return name;
  }
}
var sayMyName = setName('고무곰');
sayMyName();
  • 스코프는 정의될 때 결정된다.
  • 클로저란 이미 생명 주기가 끝난 외부함수의 변수를 참조하는 함수를 의미하기도 하지만, 반드시 이런 경우에만 클로저를 활용하는 것은 아니다.

지역변수 만들기

  • 클로저를 활용하는 대표적인 예
    • private member 만들기
  • 외부로부터 접근 제어. 전역 스코드 변수 최소화 등의 이점을 위해
  • 자동차 게임
    • 차량별로 연료량연비는 랜덤
    • 유저별로 차량 하나씩 고르면 게임 시작
    • 각 유저는 자신의 턴에 주사위를 굴려 랜던하게 나온 숫자만큼 이동
    • 만약 연료가 부족하면 이동 불가
    • 가장 멀리 간 사람이 승리
var car = {
  fuel: 10, // 연료(l)
  power: 2, // 연비(km/l)
  total: 0,
  run: function(km) {
    var wasteFuel = wasteFuel;
    this.total += km;
  }
};
  • 외부에서 power, fuel에 접근 가능하므로 치트키를 쓰는 것과 마찬가지
  • 즉, 외부에서 직접 변경할 수 없도록 하자! 스코프 활용
    • 외부에 노출을 막고 외부에 공개할 기능을 return
var createCar = function(f, p) {
  var fuel = f;
  var power = p;
  var total = 0;
  return {
    run: function(km) {
      var wasteFuel = km / power;
      if(fuel < wasteFuel) {
        console.log('이동 불가');
        return;
      }
      fuel -= wasteFuel;
      total += km;
    }
  }
};
var car = createCar(10, 2);
  • 외부에는 run만 공개
  1. 함수에서 지역변수 및 내부함수 등을 생성한다.
  2. 외부에 노출시키고자 하는 멤버들로 구성된 객체를 return한다.
  • return한 객체에 포함되지 않은 멤버들은 private하다.

  • return한 객체에 포함된 멤버들은 public하다.

  • 함수 내부에서 다시 함수를 return하면

  • return된 함수를 그 함수가 최초로 선언될 당시 정보를 유지한다.

  • 그래서 외부에 노출할 데이터만 return하면 return하지 않은 데이터는 모두 외부에서 접근을 제한할 수 있다.

  • 이에 따라 지역변수를 안전하게 보호할 수 있으며

  • 그러면서도 외부에 지역변수의 변경 권한을 넘겨줌으로써 데이터를 활용할 수 있다.

  • 객체지향 프로그래밍, 함수형 프로그래밍의 쿼리에 클로저를 많이 사용하기 때문에 반드시 알아야할 지식이다.


prototype

prototype과 constructor, proto

  • Constructor -> new -> instance

  • prototype - -> proto

  • 즉, 생성자 함수의 프로토타입과 instance의 __proto__라는 프로퍼티는 같은 객체를 참조한다.

  • __proto__는 내부 프로퍼티에 접근할 때 생략할 수 있다.

  • 하지만 proto 프로퍼티는 살아있는 것이다.

  • 예시

  • Array -> new -> [1, 2, 3]

  • Array.prototype(배열 메서드 모두 포함) - -> [1, 2, 3]

  • [CONSTRUCTOR]

  • [CONSTRUCTOR].prototype.constructor

  • (Object.getPrototypeOf([instance])).constructor

  • [instance].proto.constructor

  • [instance].constructor

메소드 상속 및 동작 원리

function Person(n, a) {
  this.name = n;
  this.age = a;
}

var gomu = new Person('고무곰', 30);
var iu = new Persion('아이유', 25);

gomu.setOlder = function() {
  this.age += 1;
}
gomu.getAge = function() {
  return this.age;
}
iu.setOlder = function() {
  this.age += 1;
}
iu.getOlder = function() {
  return this.age;
}
function Person(n, a) {
  this.name = n;
  this.age = a;
}
Person.prototype.setOlder = function() {
  this.age += 1;
}
Person.prototype.getAge = function() {
  return this.age;
}
var gomu = new Person('고무곰', 30);
var iu = new Persion('아이유', 25);
gomu.__proto__.setOlder();
gomu.__proto__.getAge(); // NaN

gomu.setOlder(); // __proto__가 생략이 가능하므로, this는 gomu를 가리킨다.
gomu.getAge(); // 31
Person.prototype.age = 100;
gomu.__proto__.setOlder();
gomu.__proto__.getAge(); // 101

gomu.setOlder(); 
gomu.getAge(); // 31

prototype chaining

  • Array -> new -> [1, 2, 3]

  • Array.prototype(배열 메서드 모두 포함) - -> [1, 2, 3]

  • 즉, Array 프로토타입은 객체이다.

    • Object -> new -> Array.prototype이므로
    • Object.prototype - -> Array.prototype
  • 또한 __proto__는 생략이 가능하기 때문에 마치 자신이 호출하는 것처럼 사용 가능

  • 프로토타입은 모두 객체이므로 모든 데이터 타입은 한결같이 이와 동일한 구조를 따른다.

  • 예시

    • Number -> new -> 10
    • Number.prototype - -> 10
    • 숫자 리터럴의 경우는 객체가 아니기 때문에 proto 프로퍼티가 없지만 사용자가 숫자 리터럴을 객체인 것처럼 접근(메서드를 사용하려고 하면)하면 js가 자동으로 Number 생성자 함수의 instance로 변환한다.

사각지대

Class

prototype static 메서드 및 static 프로퍼티

class 상속 구현

References

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.