[self study] 코어자바스크립트 정리

SeoYng·2022년 2월 3일
0
post-thumbnail

🌖 실무를 시작한지 어느덧 1년... ⏰

이제 구글신님과 경험을 통해 기능 구현은 잘할수 있다! 라는 자신감이 생겼지만
정작 마음속에 남아있는 근데 왜이렇게 돌아가지 하는 의문점들은 해소하지 못하고 있었다.
그러던 중 자바스크립트님을 깊게 공부해보지 못한 것이 아닌가 하는 생각이 들었고..
(취준시절은 이해되는것에 한계가 있었던 것 같다. 넘나 어렵..😑)
그러던 중 인강도 있고 책도 두껍지도 않으면서 깔꼼하고 컬러풀한 책을 찾았다.

다 읽고 나니 겉모습만 훌륭한것이 아니라 결론적으로
자바스크립트를 이해하는데 너무 도움이 되었던 책이었다
재미도 있고 정리도 잘되어있어서 2일만에 술술 다 보았던 것 같다
❗️ 강추 👍

📚 참고 자료

코어 자바스크립트 [정재남님] 책 - 쿠팡

코어 자바스크립트 [정재남님] - 인강


🤔   데이터 타입

  • 자바스크립트의 데이터 타입은 크게 두가지
기본형참조형
number, string, boolean, null, undefined, symbol그 외
값이 담긴 주솟값을 바로 복제값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값 복제
불변성을 띔가변값인 경우가 많지만 변경불가능한 경우도 있고 불변값으로 활용도 가능

  • 변수 영역에 값을 직접 대입하지 않고 주소값을 대입(변수 영역과 데이터 영역 분리)하는 이유

1) 데이터 변환을 자유롭게 할 수 있게 함
2) 메모리를 더욱 효율적으로 관리할수 있기 때문
3) 중복된 데이터에 대한 처리 효율도 높아짐

값을 직접 저장값의 주소를 저장
데이터 할당시에는 빠름데이터 할당시에는 느림
비교에 비용이 많이 듦비교에 비용이 들지 않음
메모리 낭비 심함메모리 낭비 최소화

  • 엄밀히 따지면 자바스크립트의 모든 데이터 타입은 참조형 데이터.

어떤 데이터 타입이던 변수에 할당하기 위해서는 주솟값을 복사해야하기 때문.
기본형은 주솟값을 복사하는 과정이 한 번만 이뤄지고 참조형은 한 단계를 더 거침

  • 원본 객체는 변하지 않아야 하는 경우 불변 객체가 필요

  • 얕은 복사와 깊은 복사

얕은 복사깊은 복사
바로 아래 단계의 값만 복사내부의 모든 값들을 찾아 전부 복사 (재귀적으로 구현)

순수한 정보를 다룰때 JSON 문자열로 전환했다가 다시 JSON객체로 바꿔 구현하는 방법도 있음

  • undefined와 null
undefined와null
어떤 변수에 값이 존재하지 않을 경우사용자가 명시적으로 '없음'을 표현하기 위해 대입

< undefined가 반환되는 경우 >

1) 값을 대입하지 않은 변수, 주소를 지정하지 않은 식별자에 접근할 때
2) 객체 내부의 존재하지 않는 프로퍼티에 접근할 때
3) return 문이 없거나 호출되지 않는 함수의 실행결과

->>> 직접 undefined를 할당하지 않는것을 권장, 비어있음을 나타내고 싶을때 null을 사용

< let, const >
let, const는 할당하지 않은채로 초기화를 마쳐
TDZ에 들어간것처럼 보이고 호이스팅 되지않는다고 여겨짐

< 자바스크립트의 버그 >
typeof null === object

  • 변수는 변경가능한 데이터가 담길 수 있는 공간, 식별자는 변수의 이름

🤔   실행 컨텍스트

실행할 코드에 제공할 환경 정보들을 모아놓은 객체
하나의 실행컨텍스트를 구성하는 방법은 함수를 실행하는 것

블록스코프는 독립된 공간의 역할은 하지만 별개의 실행컨텍스트는 생성하지않음

실행컨텍스트가 활성화되는 시점에 선언된 변수를 끌어올리고 외부 환경정보를 구성한다.
해당 컨텍스트에 관련된 코드들을 실행하는데 필요한 환경 정보들을 수집하여 실행컨텍스트 객체에 저장

컨텍스트내의 식별자 정보 + 외부환경정보

VariableEnvironmentLexicalEnvironment
선언시점의 스냅샷으로 변경사항이 반영되지 않음처음에는 VariableEnvironment와 같지만 변경사항이 반영
식별자 정보 수집식별자 데이터 추적

environmentRecordouterEnvironmentReference
매개변수명, 식별자, 함수명 등을 수집직전 컨텍스트의 LexicalEnvironment 저장
순서대로 수집하여 식별자 정보들이 저장, 변수명을 코드 실행전에 알게 됨자신이 선언된 시점의 LexicalEnvironment 참조
호이스팅 현상 발생식별자의 유효범위를 안에서부터 검색해내가는 스코프 체인과 관련
  • 스코프 체인

가장 가까운 자신부터 점점 멀리 있는 스코프로 식별자를 찾아나가는 것

무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능 (변수 은닉화)

  • 콜스택

현재 어떤 함수가 동작중인지 다음엔 어떤 함수가 호출될 예정인지 등을 제어


🤔   this

기본적으로 실행 컨텍스트가 생성될 때 결정, 즉 함수를 호출할 때 결정

  • this가 가르키는 것

1) 전역공간에서 this는 전역객체(window)를 참조
2) 메서드로서 호출한경우 (~~~.func(), ~~~[]() - 앞에 객체가 명시 되어 있는 경우)
     메서드 호출 주체를 참조(~~~)
3) 함수로서 호출한 경우 전역객체를 참조 메서드 내부함수에서도 동일
4) 콜백함수 내부에서의 this는 제어권을 넘겨받은 함수가 정의한 바에 따르며 그렇지 않은경우 전역객체 참조
5) 생성자 함수에서의 this는 생성될 인스턴스 참조

함수메서드
자체로 독립적인 기능을 수행자신을 호출한 대상 객체에 관한 동작을 수행

  • 명시적 this 바인딩 call, apply, bind

call, apply 메서드는 this를 명시적으로 지정하면서 함수또는 메서드를 호출

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  /* 기능적으로 call과 완전동일, 두번째 인자를 배열로 받음 */
  // Product.apply(this, [name, price]); 
  this.category = 'food';
}

console.log(new Food('cheese', 5).name);
// expected output: "cheese"

bind메서드는 this및 함수에 넘길 인수를 일부 지정하여 새로운 함수를 만듦
call과 비슷하지만 즉시 호출하지 않고 새로운 함수를 반환
즉, 함수에 this를 미리 적용
bind 메서드를 적용한 함수는 name프로퍼티에 자동으로 bound라는 접두어가 붙음

const module = {
  x: 42,
  getX: function() {
    return this.x;
  }
};

const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined

const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
  • 전역공간

자바스크립트의 모든 변수는 실은 특정 객체의 프로퍼티로 동작
전역변수 선언시 이를 전역객체의 프로퍼티로 할당

  • 내부함수에서 this를 우회하는 방법
const outer = {
  	const inner1 = function () {
    	console.log(this); // Window { ... }
    };
	const self = this;
  	const inner2 = function () {
    	console.log(self); // { outer: f }
    };
}
  • this를 바인딩하지 않는 함수

화살표 함수는 실행 컨텍스트를 생성할 때 상위 스코프 this를 그대로 활용할 수 있음

실행 컨텍스트 생성 시 this바인딩하는 과정이 제외,
접근하고자 하면 스코프체인상 가장 가까운 this에 접근

const outer = {
	const inner3 = () => {
      	console.log(this); // { outer: f }
    }
}

🤔   콜백 함수

다른 코드의 인자로 넘겨주는 함수제어권도 함께 위임
콜백함수를 넘겨받은 코드는 콜백함수를 필요에 따라 적절한 시점에 실행

  • 제어권을 넘겨받은 코드는 다음과 같은 제어권을 가짐

1) 콜백함수를 호출하는 시점을 스스로 판단하여 실행
2) 인자로 넘겨줄 값들 및 순서가 정해져 있음 (파라미터가 정해져있음)
3) this가 무엇을 바라보도록 할지 정해져 있는 경우가 있음 (ex- addEventListener)
-> 정해지지 않은 경우 전역객체를 바라봄. 임의로 this를 바꾸고 싶은 경우 bind를 활용

  • 대표적인 예제로 setInterval, setTimeout, addEventListener 등이 있음
const callbackFunc = () => {
	console.log('callback!')
};

let timer = setInterval(callbackFunc, 200); // timer의 변수에는 setInterval의 ID값이 담김
  • 콜백 함수로 어떤 어떤 객체의 메서드를 전달하더라도 메서드는 메서드가 아닌 함수로서 호출
    -> this가 다름 (해당객체를 this로 바라볼 수 없음)

  • 콜백지옥과 비동기 제어

동기적 코드비동기적 코드
즉시 처리가 가능한 대부분의 코드별도의 요청, 실행 대기, 보류 등과 관련된 코드


🤔   클로저

여러 함수형 프로그래밍 언어에서 등장하는 보편적인 특성으로
이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 함수

외부에서 선언한 변수를 참조하는 내부함수에서만 발생하는 현상
-> 외부함수의 LexicalEnvironment가 가비지 컬렉팅 되지 않는 현상

함수와 그 함수가 선언될 당시lexical environment(outerEnvironmentReference)의 상호관계에 따른 현상

유효범위가 사라진 후에도 호출할수 있는 함수

어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상

let outer = function () {
	let a = 1; // 외부 변수
 	let inner = function () {
    	return ++a;
    } 
    return inner; // inner 자체를 return 하여 이를 참조하는 a가 살아있음
};

let outer2 = outer();

가비지 컬렉터는 어떤 값을 참조하는 변수가 하나라도 있다면 그 값은 수집대상에 포함시키지 않는다.
즉, 좀비처럼 살아있게 되는 것!

  • 클로저와 메모리 관리

필요성이 사라진 시점에 더는 메모리를 소모하지 않도록
식별자에 기본형데이터(보통 null / undefined)를 할당하여 참조카운트를 0으로 만듦

  • 클로저 활용 사례

1) 콜백함수 내부에서 외부 데이터를 사용하고자 할 때

let buildFunc = function (param) { // 외부 데이터 : param
	return function() {
    	console.log('param is ', param);
    }
}

$el.addEventListener('click', buildFunc(param));

2) 접근 권한 제어(정보 은닉)

어떤 모듈의 내부로직에 대해 외부로의 노출을 최소화하여
모듈간의 결합도를 낮추고 유연성을 높이고자 하는 개념

클로저를 활용하여 외부 스코프에서 함수 내부의 변수들 중 선택적으로 일부의 변수에 대한 접근 권한 부여 가능 (public한 값과 private한 값을 구분가능)

let outer = function () {
	let a = 1; // 공개 변수 (public)
	let b = 2; // 지역 변수 (private)
 	let inner = function () {
    	return ++a;
    } 
    return inner;
};

let outer2 = outer();

3) 커링 함수

러 개의 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠 순차적으로 호출될 수 있게 체인 형태로 구성한 것

마지막 인자가 넘어갈 때까지 함수 실행을 미루는 셈-> 지연실행
원하는 시점까지 지연시켰다가 실행하는 것이 요긴한 상황에서 적합

const curry = func => a => b => c => d => func(a, b, c, d);

  • 내부함수와 외부함수를 전달하는 방법

1) return으로 전달
2) 콜백으로 전달

  • Symbol.for 메서드는

전역 심볼공간에 인자로 넘어온 문자열이 이미 있으면 해당 값을 참조하고
선언되어 있지 않으면 새로 만드는 방식으로
어디서든 접근 가능하며 유일무이한 상수를 만들고자 할때 사용


🤔   프로토타입

자바스크립트는 프로토타입 기반언어

클래스 기반언어프로토타입 기반언어
상속 사용어떤 객체를 원형으로 삼고 이를 복제(참조)함으로써 상속과 비슷한 효과를 얻음


prototype 객체 내부에는 인스턴스가 사용할 메서드를 저장.
인스턴스에서도 숨겨진 프로퍼티인 __proto__ ([[Prototype]])를 통해 이 메서드들에 접근할 수 있게됨
__proto__를 통해 직접 접근하기보다 getPrototypeOf()를 이용하는 것을 권장

__proto__생략가능한 프로퍼티이기 때문에 바로 접근가능

  • 개념 상세히 설명

1) 자바스크립트는 함수에 자동으로 객체인 prototype 프로퍼티를 생성
2) 해당 함수를 생성자 함수로 사용할 경우 (new와 함께 호출) 생성자 함수의 prototype 프로퍼티를 참조하여 인스턴스에 숨겨진 프로퍼티 __proto__ 생성
3) __proto__생략가능하기 때문에 인스턴스도 마치 자신의 것처럼 해당 메서드나 프로퍼티에 접근할 수 있음

  • 콘솔에서 확인

    짙은색은 열거가능한 프러퍼티, 옅은색은 열거할 수 없는 프로퍼티
    for in등으로 프로퍼티에 접근하고자 할 때 접근가능 여부를 색상으로 구분
    인스턴스는 해당 생성자 함수의 이름을 표기함으로써 해당 함수의 인스턴스임을 표기
    prototype에 있는 constructor 프로퍼티는 인스턴스가 자신의 생성자 함수가 무엇인지 알고자할 때 사용

  • 프로토타입 체인 & 프로토타입 체이닝

프로토타입 체인
어떤 데이터의 __proto__프로퍼티 내부에 다시 __proto__ 프로퍼티가 연쇄적으로 이어진것

프로토타입 체이닝
프로토타입 체인을 따라가며 검색하는 것

let array = [1, 2]
/* .toString()은 object prototype */
array.toString() // object prototype속성을 체이닝을통해 사용할 수 있음
// '1,2'

어떤 생성자 함수이든 prototype은 객체이기 때문에 Object.prototype이 언제나 프로토타입 체인의 최상단에 존재하게 됨

객체만을 대상으로 동작하는 객체 전용 메서드들은 부득이 Object에 스태틱메서드로 부여할 수 밖에 없음

메서드가 오버라이드된 경우에는 자신으로부터 가장 가까운 메서드에만 접근 가능


🤔   클래스

클래스인스턴스
특성을지닌 집단, 추상적인 개념클래스의 속성을 지니는 실존하는 개체

  • 스태틱 메서드

인스턴스에서 직접 접근할 수 없는 메서드

  • ES6에서 클래스 문법 등장

ES6 클래스 문법으로 이전보다 간단하게 구현 가능
ES5까지는 프로토타입 체이닝을 잘 연결하여 상속을 구현


profile
Junior Web FE Developer

0개의 댓글