면접대비로 JS를 다시한번 공부할 겸 블로그에 정리한 글 + 모던 deep dive책을 다시 한번 봐가면서 정리한 글입니다.
넷스케이프에서 웹 페이지 보조적인 기능을 위해 브라우저에서 동작하는 경량 프로그래밍 언어 도입
→ 브랜던 아이크의 자바스크립트
그러나 JScript의 출시로 인해 위기를 맞았지만 MS와 넷스케이프가 경쟁하면서 크로스 브라우징 이슈가 발생 이로 인해 JS의 필요성이 대두되어 ECMA인터내셔널에서 표준화된 JS인 ECMAScript의 탄생
Node.js: 자바스크립트를 브라우저 이외의 환경에서 동작시킬 수 있는 런타임 환경(비동기 IO와 단일 스레드 이벤트루프 지원 → SPA에 적합)
ECMAScript는 프로그래밍 문법의 핵심을 담당하고 자바스크립트는 일반적으로 프로그래밍 언어이면서도 클라이언트 사이드 Web API(DOM, BOM, XMLHttpRequest, Fetch)등을 아우르는 개념
JS특징
구형브라우저를 위한 바벨과 같은 트랜스파일러(컴파일러) 사용
컴파일: 한 언어로 작성된 소스 코드를 다른 언어로 변환
트랜스파일: 한언어로 작성된 소스 코드를 비슷한 수준의 추상화를 가진 다른 언어로 변환
변수란 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 메모리 공간을 식별하기 위해 붙인 이름
식별자란 어떤 값을 구별할 수 있는 고유한 이름
실행컨텍스트를 통해 식별자와 스코프 관리
가비지 콜렉터란 실행컨텍스트가 종료되어 더이상 참조할 수 없는 값들을 mark-and-sweep
이라는 알고리즘으로 루트부터 시작하여 모든 객체를 돌면서 방문할 수 없는 곳(도달 가능성 기준으로 도달하지 못한곳)을 메모리에서 삭제한다.
변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징(var 변수만)
식별자 네이밍 규칙으로 문자, 숫자, 언더스코어, 달러 사인을 사용할 수 있다. 대신 처음에 숫자로 시작하지는 못한다.
값이란 식이 평가되어 생성된 결과
리터럴이란 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법
표현식이란 값으로 평가될 수 있는 문
문이란 프로그램을 구성하는 기본 단위이자 최소실행 단위
문법적인 의미를 가지고 더 이상 나눌 수 없는 코드의 기본 요소
→ 변수에 할당을 해보면 표현식인문과 표현식이 아닌문을 확인할 수 있다.
자동적으로 브라우저가 사용자에 대한 별도의 재설치를 요구하지 않고도 업데이트가 가능한 브라우저
JS는 선언이 아닌 값의 할당에 의해 타입이 결정된다. 또한 언제든지 타입이 동적으로 변한다. 이로 인해 유연성은 높지만 변수 값을 추적하기 어려워 신뢰성이 떨어진다.
Obejct.is
메서드(+0과 -0 true로 나옴)삼항 조건 연산자 표현식은 값으로 평가할 수 있는 표현식인 문이다.
피연산자의 데이터 타입을 문자열로 반환 → 그러나 null과 array를 반환하지 않음.(이를 통해 완전하게 객체의 타입이 무엇인지 확인하는것은 어려움
타입 변환이란 개발자가 의도적으로 값의 타입을 변환시키는 것(명시적 타입변환이라 한다.)
JS엔진에 의해 암묵적으로 타입 자동변환 되는 것을 암묵적 타입변환이라 한다.
논리곱 연산자와 논리합 연산자는 피연산자 타입을 Boolean 값으로 변환하지 않고 그대로 반환하는 것
?.
좌항이 null
또는 undefined
이면 undefined
를 반환하고 그렇지 않으면 우항의 프로퍼티 값 참조
??
좌항이 null
또는 undefined
이면 우항의 피연산자를 반환하고 그렇지 않으면 좌항의 피연산자를 반환한다.
isNaN(is not a number)은 숫자인지 아닌지를 판별하는 것
Number.isNaN(is NaN)은 NaN
그 자체인지 아닌지를 판별
원시타입은 단 하나의 값
객체타입은 다양한 타입의 값을 하나의 단위로 구성한 복합적인 자료구조
객체란 0개 이상의 프로퍼티로 구성된 집합이고 프로퍼티는 key와 value로 구성된다.
프로퍼티 값이 함수인 경우 이것을 메서드라고 부른다.
프로퍼티키와 프로퍼티 값의 이름이 동일할 때 프로퍼티키 생략이 가능하다.
원시타입(불변성, 데이터의 신뢰성 보장)
객체타입(프로퍼티 접근을 위해 히든클래스 방식)
결국 메모리에 저장된 값을 복사해서 전달한다는 면에선 동일(원시 값? or 참조 값)
불변이라는 의미가 메모리에 저장된 값이 변하지 않는다는 의미이며 변수에 할당 시에 완전히 새로운 값이 만들어져 재할당 되기 때문에 데이터의 신뢰성이 보장된다.
객체를 복사할 때 1단계 까지만 복사하는 것을 얕은 복사라고하며 내부에 있는 모든 값들을 참조 값이 아닌 완전히 복사할 때 깊은 복사라고 한다.
객체안에 내부에 중첩된 객체가 있는 경우 얕은 복사 진행 시 참조 값으로 복사되는 것이 1단계 까지만 복사하는 것이다.
얕은복사 방법: object.assign, 전개연산자
깊은복사 방법: 재귀함수, lodash
call by value: 값에 의한 호출(함수 안에서 인자의 값이 변경되어도 외부 변수의 값은 변하지 않음)
call by reference: 참조에의한 호출(함수안에서 인자의 값이 변경되면 아규먼트로 전달된 객체의 값이 변경)
call by reference, call by value in JS
C와 C++과 같은 포인터가 있는 언어에서는 이 개념이 그대로 적용된다고 생각하지만 JS의 경우 값에 의한 전달(call by sharing이라고도 하지만 공식적인건 X)만 적용되어 실제 객체를 파라미터로 넘겼을 때 참조값에 존재하는 동일한 값이 복사되어 전달되기 때문이다.
JS에서 함수는 일급객체!
함수 선언문의 경우 JS엔진이 생성된 함수를 호출하기 위해 함수 이름과 동일한 식별자를 암묵적으로 생성하여 함수객체를 할당하여 호출할 수 있다.
함수형 프로그래밍이란 순수 함수를 통해 외부 상태를 변경하는 부수효과를 최소화해서 불변성을 지향하는 프로그래밍 패러다임
객체를 불변하게 만들려면 Object.freeze()
라는 메서드를 이용하여 깊은 객체 동결을 재귀함수로 구현하여 불변한 객체를 만들 수 있다.
스코프란 식별자가 유효한 범위를 말한다.
코드가 어디서 실행되며 주변에 어떤 코드가 있는지를 말한다.
정적 스코프: 어디서 정의했는지에 따라 상위스코프 결정
동적 스코프: 어디서 호출했는지에 따라 상위스코프 결정
함수의 상위스코프는 언제나 자신이 정의된 스코프이고, 함수가 호출될 때마다 함수의 상위스코프를 참조할 필요가 있기 때문에 내부슬롯 Environment에 상위 스코프를 기억한다.
호이스팅은 스코프 단위로 동작!
es6이전 변수를 선언하기 위해 이 키워드를 사용
es6에 도입된 문법으로 아래와 같은 특징
let
const
__proto__
접근자 프로퍼티 (프로토타입 내부 슬롯 접근이 가능함)
getOwnPropertyDescriptor & getOwnPropertyDescriptors
defineProperty & defineProperties
Object.preventExtensions (프로퍼티 추가 금지)
확인 메서드: Object.isExtensible
Object.seal(객체 밀봉 - 읽기와 쓰기만 가능)
확인 메서드: Object.isSealed
Object.freeze(객체 동결 - 읽기만 가능)
확인메서드: Object.isFrozen
객체 동결 재귀 함수
function deepFreeze(target) {
if(target && typeof target === 'object' && !Object.isFrozen(target)) {
Object.freeze(target);
// 모든 프로퍼티 순회
Object.keys(target).forEach(key => deepFreeze(target[key]));
}
return target;
}
deepFreeze(객체);
생성자 함수에서 다른 객체를 반환하면 명시된 객체가 반환되고 원시값은 암묵적으로 this가 반환된다. → 따라서 내부에선 return문 반드시 생략!
모든 함수 객체는 callable 이지만 constructor
일 수도 있고 non-constructor
일 수도 있다.
non-constructor를 new와 같이 호출하면 TypeError
발생!
new.target → 함수 자신을 가리킨다. 이를 사용하여 생성자 함수 역할을 제한할 수 있음
new 연산자 없이 일반 함수로서 호출된 함수 내부의 new.target은 undefined이다.
if(!new.target) { return new Circle(radius); }
스코프 세이프 생성자 패턴
if(!this instanceof Circle) { return new Circle(radius); }
hasOwnProperty
메서드 → 인수로 전달받은 프로퍼티 키가 객체 고유의 프로퍼티 키인 경우에만 true이고 프로토타입 상속으로 받은 키는 false 반환
for(const key in o) {
if(o.hasOwnProperty(key)) {
console.log(key);
}
}
이렇게 사용하는 것 보다 Object.hasOwnProperty.call(o, key)) 로 사용하는 것이 더 좋다고한다. o가 이 메서드를 가지고 있지 않을 수도 있기 때문!
JS → 프로토타입 기반 객체지향 프로그래밍 언어(상속을 구현하는 메커니즘)
객체 지향은 객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임이다.
__proto__
접근자 프로퍼티__proto__
접근자 프로퍼티를 통해 자신의 prototype에 간접적으로 접근이 가능Object.getPrototypeOf
메서드나 Object.setPrototypeOf
메서드 사용 권장가상적인 생성자 함수를 가지며 프로토타입과 생성자 함수는 단독으로 존재할 수 X → 언제나 쌍으로!
ex) object, array, function, regexp
생성자 함수가 생성되는 시점에 생성!
빌트인 생성자 함수또한 마찬가지
추상 연산 OrdinaryObjectCreate
에 전달되는 인수에 의해 결정된다.
사용자 정의 함수는 constructor 프로퍼티만 가지고 프로토타입을 만들기 때문에 메서드들을 직접 구현해주어야함.
in 연산자, Reflect.has, hasOwnProperty 프로퍼티 키가 객체 고유의 프로퍼티 키인 경우 true 반환
for..in(enumerable이 true이고 상속받은 프로토타입의 프로퍼티까지 보여줌)
객체 고유만 보려면 Object.keys, values, entries 를 사용!
문자열, 숫자, 불리언 값에 객체처럼 접근하면 생성되는 임시 객체를 래퍼객체라고 하고 이 과정이 끝나고 다시 원시값으로 되돌린다. (Number, String, Boolean의 메서드들을 사용할 수 있게 해줌)
어떤 객체보다 먼저 생성되는 특수한 객체 → globalThis라는 ECMAScript 표준 전역 객체 통일 식별자가 등장
자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수이다.
this 바인딩은 함수 호출 방식에 의해 동적으로 결정!
bind 메서드는 일반적으로 메서드의 this와 내부 중첩, 콜백함수의 this가 불일치하는 문제를 해결하기 위해 사용
실행 컨텍스트는 식별자를 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘
렉시컬 환경: 식별자와 스코프를 관리
실행컨텍스트 스택: 코드 실행 순서
반복문이 실행될 때마다 코드 블록을 위한 새로운 렉시컬 환경을 생성!
클로저란 외부함수보다 중첩함수의 생명주기가 더 길고, 외부 함수의 변수를 참조하고 있는 함수를 클로저라고 한다.
주로 상태를 안전하게 은닉하고 특정 함수에게만 상태변경을 허용하기 위해 사용한다.
정보은닉을 하는 이유? → 결합도를 낮추고 응집도를 높이기 위함
새로운 객체 생성의 메커니즘!
특징
const counter = {
num: 1,
increase: () => ++this.num
};
console.log(counter.increase()) // NaN
이 경우도 counter 객체안의 increase 메서드는 화살표 함수로 정의되어 있어 increase를 호출하면 객체를 가리키는 것이 아닌 전역을 참조하게 된다.
arguments객체는 유사배열 객체 → 배열 메서드 사용하려면 배열로 변환해야함
그러나 Rest파라미터는 일반 배열이기 때문에 배열메서드 바로 사용 가능
일반적인 배열 → 밀집 배열(동일한 크기의 메모리 공간에 연속적으로 나열되어 있어서 offset으로 접근가능)
연속적으로 이어져 있지 않은 배열 → 희소배열
JS 배열은 요소를 위한 각각의 메모리 공간이 동일한 크기 X, 일반적인 배열의 동작을 흉내낸 객체
유사 배열 객체는 배열처럼 인덱스로 프로퍼티 값 접근 가능 → for문으로 순회 가능
이터러블 객체는 Symbol.iterator 메서드를 구현하여 for...of문, 스프레드 문법, 배열 디스트럭처링 할당의 대상으로 사용할 수 있다.
고차 함수는 함수를 인수로 전달받거나 함수를 반환하는 함수를 말함
외부 상태의 변경이나 가변데이터를 피하고 불변성을 지향하는 함수형 프로그래밍에 기반을 둠
심벌이란 변경 불가능한 원시 타입의 값이다.
Symbol은 호출 시마다 유일무이한 심벌 값을 생성하지만 전역 심벌 레지스트리에서 관리 X
Symbol.for은 검색에 성공 시 검색된 심벌 값을 반환 또는 전역에서 중복되지 않은 심벌 값을 단 하나만 생성하여전역 심벌 레지스트리에 저장 후 새로운 심벌 값 반환.
Symbol.keyFor은 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출할 수 있다.
Symbol은 for...in 문으로 찾을 수 없고 Object.getOwnPropertySymbols 메서드 사용시 프로퍼티 중 심벌을 찾을 수 있다.
자바스크립트가 기본 제공하는 빌트인 심벌 값으로 Well-known Symbol이라고 하며 for...of 문으로 순회가 가능하며 이를 호출 하면 이터레이터(next()를 소유하고 있음) 를 반환하도록 되어있다.
ES6에서 도입된 순회 가능한 데이터 컬렉션을 만들기 위한 규칙이다.
데이터 소비자와 데이터 공급자를 연결하는 인터페이스 역할 (전에는 다양한 방법으로 순회를 할 수 있었지만 일원화 하여 효율적으로 순회 방법 관리)
done 프로퍼티 생략 시 무한 이터러블 생성이 가능하다.
불필요한 데이터를 미리 생성하지 않고 필요한 데이터를 필요한 순간에 생성하여 빠른 실행속도, 불필요한 메모리 소비를 하지 않고 무한도 표현 가능하다.
layout 과정은 cpu가 paint과정은 gpu가 하기 때문에 비용측면에 있어서 layout과정이 더 높다.
무조건 리플로우가 발생해야 리페인트가 발생하는 것은 아니다.
리플로우의 비용 > 리페인트 비용
DOM이란 문서 객체 모델로 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API를 제공한다.
EventTarget 객체
둘다 유사 배열 객체이면서 이터러블 이지만 노드 객체의 상태변화를 실시간으로 반영하는 살아있는 객체이다. NodeList의 대부분은 과거 정적 상태를 유지하는 non-live객체로 childNodes 프로퍼티가 반환하는 Nodelist객체는 live객체이다.
안전하게 사용하려면 둘다 배열로 변환하여 사용하는 것을 권장한다.
성능최적화를 위해 주의해서 다루어야 한다.
innerHTML
사용자로부터 입력받은 데이터를 그대로 넣으면 XSS(크로스 사이트 스크립팅 공격)에 취약하다.
HTML 새니티제이션
사용자로부터 입력받은 데이터에 의해 발생할 수 있는 크로스 사이트 스크립팅 공격을 예방하기 위해 잠재적 위험을 제거하는 기능 (DOMPurify와 같은 라이브러리 존재)
insertAdjacentHTML
innerHTML 프로퍼티보다 효율적이고 빠르지만 HTML 마크업 문자열을 파싱하므로 XSS 공격에 취약하다.
노드를 추가하는 경우 여러개의 노드를 한번에 컨테이너처럼 묶어서 사용하고 싶은 경우 이 노드를 사용한다.
→ 리플로우와 리페인트 한번만 실행
프로그램의 흐름을 이벤트 중심으로 제어하는 프로그래밍 방식
이벤트가 발생하여 호출될 함수를 이벤트 핸들러
removeEventListener
메서드 사용
이벤트 타깃을 중심으로 DOM 트리를 통해 전파하는 것(캡처링, 타깃, 버블링)
동일한 자식 요소들이 많거나 계속적으로 추가된다고 할때 부모요소에 이벤트 위임을 하여 타깃 검사를 통해 이벤트를 발생시킴
중단하는 메서드: preventDefault
이벤트 전파방지: stopPropagation
stopimmediatePropagation → 같은 이벤트의 다른 핸들러에게도 이벤트 전달이 멈춰진다.
디바운스는 짧은 시간 간격으로 발생하는 이벤트를 그룹화해서 마지막에 한번만 이벤트 호출
→ resize 이벤트 처리나 버튼 중복 클릭 방지처리등에 사용
스로틀은 짧은 시간 간격으로 발생하는 이벤트를 그룹화해서 일정 시간 단위로 이벤트 핸들러가 최대 한 번만 호출되도록함.
→ scroll 이벤트 처리나 무한 스크롤 구현 등에 유용하게 사용된다.
JS엔진은 싱글스레드이기 때문에 2개 이상의 함수를 동시에 실행할 수 없고 블로킹이 발생한다.
비동기 처리는 다음과 같은 과정을 가진다.
HTTP의 장점을 최대한 활용할 수 있는 아키텍처이다.
restful → 이 기본원칙을 성실히 지킨 서비스 디자인
ES6에 등장한 문법으로 기존 비동기 처리의 단점을 보완하기 위해 등장하였다.
new 연산자와 함께 Promise를 호출하여 생성하고 resolve, reject 함수를 인수로 받는다.
프로미스 상태 정보를 우선 2가지로 나눌 수 있다.
pending: 비동기 처리전 수행되지 않은 상태
settled: 비동기 처리가 수행된 상태
settled 또한 2가지로 나눌 수 있다.
resolve(비동기 처리 성공), reject(비동기 처리 실패)
then, catach, finally를 제공하며 마이크로태스크 큐에 저장된다.
또한 언제나 프로미스를 반환한다.
then의 두 번째 인수로 reject를 처리하는 것보다 catch로 처리하는 것이 비동기 처리에서 발생한 에러 뿐 아니라 then 내부에서 발생한 에러까지 잡아준다.
프로미스의 후속 처리 메서드의 콜백함수가 담기는 곳
태스크 큐 → 비동기 함수의 콜백함수나 이벤트 핸들러가 존재하는 곳
ES6에서 도입되었으며 코드 블록의 실행을 일시 중지했다가 필요한 시점에 재개할 수 있는 특수한 함수
특징
function* genFunc() { yield 1; }
제너레이터 함수 호출 시 제너레이터 객체를 반환(이터러블이면서 동시에 이터레이터) next() 뿐만아니라 return, throw 메서드를 갖고 yield 표현식 까지만 실행하여 이 뒤에 오는 표현식의 평가 결과를 제너레이터 함수 호출자에게 반환한다.
이를 사용하여 비동기처리를 동기 처리처럼 구현할 수 있다.
예시
const async = generatorFunc => {
const generator = generatorFunc();
const onResolved = arg => {
const result = generator.next(arg);
return result.done ? result.value : result.value.then(res => onResolved(res));
};
return onResolved;
};
async(function* fetchTodo() {
const url = 'https://jsonplaceholder.typicode.com/todos/1';
const response = yield fetch(url);
const todo = yield response.json();
console.log(todo);
})();
async라는 함수에 제너레이터 함수를 전달받아 제너레이터 객체를 활용하여 동기적으로 구현한 모습이다.
ES8에서는 가독성 좋게 비동기 처리를 동기 처리처럼 동작할 수 있도록 async/await가 도입되었다.
async 함수는 언제나 프로미스를 반환하며 암묵적으로 반환값을 resolve하는 프로미스를 반환한다.
await 키워드는 항상 async내에서만 쓰이며, settled 상태가 되었을 때 프로미스를 resolve한 처리를 반환한다.
또한 명시적으로 호출이 가능하기 때문에 에러처리가 가능하다.(try ... catch문을 사용하여)
async함수 내에서 에러처리를 하지 않는다면 발생한 에러를 reject하는 프로미스를 반환하기 때문에 catch 후속 처리 메서드를 사용해 에러를 캐치할 수 있다.
We at Escorts in Electronic, here in Bangalore, are proud to introduce a list of the best Indian escorts in the city. We have carefully selected these beautiful young girls and their outstanding service because we care about making your experience as enjoyable as possible.
https://www.thebangaloreescorts.in/escorts/electronic-city.html
딥다이브를 정리해놓으신 것같네요 너무 잘 읽었습니다.