ES6 기초를 탄탄하게!

5 minute read

내가 주로 사용하고 있는 기술들은 Node js와 React 모두 js를 기반으로 다뤄지는 기술들이다.

때문에 js에 대한 기초를 단단하게 다지고 싶어 인프런에서 강의를 들었다.

링크 : https://www.inflearn.com/course/ecmascript-6-flow

es6-basic-course

강의를 들으면서 내가 기존에 모르고 있었던 내용 혹은 더 자세하게 알아두어야 할 내용을 이곳에 적어두었다.

블록스코프, 함수스코프

블록스코프 (let, const)

변수 선언이 속해있는 블록에서만 기록되어 그 밖의 블록에서는 쓰이지 못한다

함수스코프 var

변수선언이 속해있는 함수 안에서만 기록되어 그밖 다른 함수 혹은 상위 함수에서 쓰이지 못한다.

(for문에서 var i = 0하고 돌린다음에 콘솔을 찍어보면 돌렸던 흔적?이 나오는게 이 때문이다.)

호이스팅

자바스크립트 실행전에 선언된 변수 함수들을 한번 훑는 것

->(내 생각엔 이 개념이 js를 비동기로 실행이 가능하도록 만들어주는게 아닐까 싶다.)

자바스크립트에서 함수를 선언하면 지정된 단위 안에서 변수들을 사용하고 지정된 단위안에 없는 변수는 상단 범위를 탐색한다.

var의 호이스팅

var : 변수명만 위로 끌어올리고 undefined 할당

(상단 스코프에서 선언된 변수이름과 같은 변수이름을 사용해야할때 주의해야한다.)

-> var이라도 상단에서 선언된 이름과 같은 이름으로 선언해버리면 상단 스코프로 탐색을 진행하지 않는다

let, const의 호이스팅

let, const : 변수명만 위로 끌어올리고 끝 할당을 하지 않는다

(많은 서적에서는 이해를 돕기위해 let, const는 호이스팅을 하지 않는다고 알려주고 있다.)

const의 함수스포크에 관한 예시

(function (){
    const a = 10;
    (function(){
        console.log(a); //a가 위에 선언이 되었지만 ReferenceError가 난다.
        const a = 20;
    })();
    console.log(a); //10
  })()

const의 재할당 예시 코드

const obj = {a : 1};
const obj = 1; //에러
const obj.a = 2; // 에러 안남

js에서의 this

객체안의 선언되는 매소드, 그 안에서 쓰이는 this는 그 객체를 담고 있지만 아닌 경우는 this는 기본적으로 window 객체를 의미한다.

  var obj ={
      value : 1,
      myMethod : function(){
          this.value = 2; //obj함수의 value
          (function (){
              this.value = 3; //window객체(전역변수)의 value
          })
      }

  }

template literal을 중복처리 가능하다

`my name is ${`yunsuu`}` // "my name is yunsuu"

trim 메소드를 이용해서 줄바꿈 정리를 하기도 한다.

템플릿 리터럴은 태그함수라는 것을 이용한 호출도 가능하다

string.raw를 이용해서 이스케이프 문자도 그대로 데이터 상으로 볼 수 있다.

const tag = function(strs, ...args){
    return {strs: strs, args}
}
const res = tag`순서가 ${1}이렇게 ${2}`
//strs -> ["순서가", "이렇게", ""]
//args -> [1, 2]

반복문 매소드

  • foreach : for 문과 똑같다. for문을 좀더 편하게 적합

  • map : 배열을 이용해 새로운 “배열“을 만들 때 적합

  • reduce : 배열을 이용해 새로운 ““을 만들 때 적합

spread operator (펼치기 연산자)

  • 배열의 각 인자를 펼친다.

  • getter(받는입장) 일때는 배열로 받아들이고

  • setter(펼치는 입장) 일때는 펼치기

  • iterable(반복가능)한 모든 데이터는 펼칠 수 있다 -> 왠만한건 다 펼친다.

  • 얕은 복사만 수행한다.

펼치기 연산자 적용 코드

arr = [1,2,3,4]
console.log(...arr) //1~4 출력

sum = function(..args){
    //args가 인자의 값들을 배열로 받아온다.
    return result //모든 인자 값을 합한걸 result라고 했을때
}

sum(1,2,3,4,5,6) //1~6의 값을 합한 값이 나온다.

객체 변수 선언 생략 (shorthand property)

  • json 객체 key와 value의 값이 같을때 문법을 생략함

이거와

var x = 10
var y = 20
var obj = {
    x : x,
    y : y
}

이게 같다

var x = 10
var y = 20
var obj = {
    x,
    y
}

객체 메소드 선언 생략 (concised method)

  • 객체 매소드를 만들때 함수의 문법을 생략 할 수 있다.

  • 매소드 본연의 성능을 향상 시킬 수 있다.

  • 함수의 프로토타입 객체를 사용하지 않기 때문에 기존 함수 선언보다 가볍다.

  • 생성자 함수로서의 기능은 하지 못한다.

메소드 선언 생략 예시

const obj = {
    name : "foo",
    getName1 () {return this.name},
    getName1 : function(){ return this.name }
}

const a = new obj.getName1() //TypeError: obj.getName1 is not a constructor
const a = new obj.getName2() //error 안남

선언을 생략해 메소드를 생성하면 prototype객체가 없기때문에 메소드가 보다 가벼워진다.

객체의 열가 순서

  1. 숫자를 오름차순으로 나열한다.
  2. 문자열을 입력 순서대로 나열한다 (음수나, 앞에 0이 붙은 숫자는 문자열)
  3. symbol이 입력된 순서로 나열된다.

this 바인딩

  1. js의 기본적으로 this 바인딩이 일어날 때는 전역객체를 바인딩한다.

  2. 현재 스코프에서 바인딩할게 없다면 상위 스코프로 바인딩을 한다.

  3. 객체 안에서 선언된 메소드의 this 바인딩은 객체로 바인딩된다. -> 객체를 가르키게 된다

단 주의할 사항은

객체의 메소드는 객체 안으로 this바인딩이 되지만

객체는 스코프를 생성하지 않기때문에 메소드가 아닌

함수의 this 바인딩은 객체가 선언된 코드레벨 기준으로 바인딩이 시도된다.

(대부분 전역 this 바인딩)

객체 안에서 메소드와 함수를 잘 구분해 어느쪽으로 this가 바인딩 되는지 주의하자!

주의사항

  • arrow function은 this 바인딩이 일어나지 않는다.

  • 그리고 객체는 스코프를 생성하지 않는다.

  • 때문에 객체 안에서 선언된 arrow function이 가르키게 되는 this는 window 전역객체이다.

객체 바인딩과 전역 바인딩의 예시 코드

//기본적인 바인딩은 window 바인딩
function checkThisInNormalFunc() {
    console.log(this === window) // true
}
checkThisInNormalFunc()

//객체 안에서의 바인딩은 객체 자기 자신을 가르킨다.
var obj = {
    name: "seo",
    print: function() {
        console.log(this.name)       // seo
        console.log(this === obj)    // true
    }
}
obj.print()

여기서 주의할점은 메소드 방식으로 호출할때 this가 객체를 가르킨다는 점

var obj = {
    print: function() {
      console.log(this == obj);
    }
}
//메소드 방식이 아닌 일반함수 방식으로 호출하기 위해 변수에 담기
var print = obj.print 
           
obj.print();      // true (메소드 방식 호출)
print();          // false (일반함수 방식 호출)

new 키워드로 객체를 생성할때 this는 전역객체가 아닌 생성된 객체를 가르킨다.

function printName() {
    var lastName = "seo";
    this.firstName = "jeong kuk"
    console.log(this.lastName + " " + this.firstName)
}
var lastName = "kim";
printName();               // kim jeong kuk
var o = new printName();   // undefined jeong kuk

생성자 함수

  • 생성자 함수는 js가 클래스 개념을 이용하기 위해 쓰여지는 개념이다.
//클래스 선언하듯이 이렇게 선언하고
function Person(name, gender) {
  this.name = name;
  this.gender = gender;
  this.sayHello = function() {
    alert(this.name + ' said "hello"');
  }
}

//new를 이용해 함수 인자에 넣어줘 리턴해주면
var zero = new Person('Zero', 'm'); // Person {name: 'Zero', gender: 'm'}
var hero = new Person('Hero', 'f'); // Person {name: 'Hero', gender: 'f'}

// Person에서 선언한 메소드들이 생성자 함수로 만들어진 객체에서 모두 사용할 수 있다.
zero.sayHello(); // 'Zero said "hello"'
hero.sayHello(); // 'Hero said "hello"'
  • 이렇게 메소드를 사용할 수 있는 이유는 prototype 객체 안에 선언된 메소드를 공유하고 있기 때문이다.

arrow function

  • arrow function은 객체의 메소드 선언시에는 선언하면 안된다! -> this가 객체를 가르키는게 아닌 전역 변수를 가르키게 된다.

  • 객체의 메소드 안에서 함수를 선언애햐할 일이 있을때는 일반 function 선언문이 아닌 arrow function 선언문을 사용해야한다. ->

예시

 const b = { 
     name : "하하",
     bb(){
         return this.name // b객체의 name (하하)
     },
     a : (x)=>{
         return this.name // window 객체의 name
     }
  }

실행컨택스트시 생성시 this 바인딩을 하지 않음 (중요!!!!)

기존 js에서는 모든 변수, 함수를 실행전 window 객체에 등록(호이스팅) 후

실행을 진행했고 이 부분이 js가 언어가 아니라고 까인 이유 중 하나이다.

하지만 es6에서는 js의 언어로도 기능을 할 수 있도록 하기위해 일정 부분을 window로 바로 등록되는 것이 아닌 블록단위로 제어할 필요가 있었다. 이러한 아이디어에서 나온 개념들이 const, let, arrow function들이다.

선언 및 실행과정에서 window 객체에 바로 등록되는 것이 아닌 많은 프로그램 언어들 처럼 블록 단위 안에서 제어가 된다이들은 호이스팅을 진행하지 않는다.

(엄밀히 따지자면 호이스팅을 진행하긴 하지만 많은 서적에서 이해를 돕기위해 호이스팅을 진행하지 않는다고 설명하는 것 같다.)

  • call apply 메소드는 정상적으로 작동한다.

  • arrow 함수도 콘솔로 까보면 prototype 프로퍼티가 없다 -> 생성자 함수를 사용할 수 없다. -> 클래스를 만들 수 없다 -> concised method(객체 매소드 선언 축약)과 유사하다.

arrow functions의 this바인딩의 구조를 보여주는 예시

const obj = {
    a: function () {
        console.log(this) // obj의 this
 
        const b = function() {
            console.log(this) //window 객체의 this
        }

        const c = () => {
            console.log(this) //obj의 this
        }
    } 
}

객체를 괄호없이 리턴할때는 요렇게

var e = x => {x:1} // x
var e = x => ({x:1}) // o