유돈노자바스크립트

review, share · 2024-7-26

← 리스트로

유돈노자바스크립트

인상깊거나 중요해 보이는걸 정리

자바스크립트는 다중 페러다임 언어다

자바스크립트는 절차적, 객체지향, 함수형 스타일의 코드를 모두 작성할 수 있다. 하지만 최고로 적절하게 제공하지는 않는다.

특정 페러다임으로 코딩 할 수는 있지만 엄청 잘 할수는 없다. 하스켈처럼 함수형에 적합한 기능을 전부 지원하지 않는다. 하지만 함수형 처럼 비슷하게 코딩할 수는 있다.

자바스크립트는 하위호완성을 보장한다

예전에 작성한 코드가 최신 브라우저에서도 잘 작동하는것이 하위호완성이다.

하지만 상위호완성을 보장하지는 않는다. 최신문법의 코드가 예전 버전의 오래된 브라우저에서는 동작하지 않는다.

상위호완성을 보완하려는 노력이 "폴리필"과 "트렌스파일러"이다.

자바스립트는 인터프리터 언어가 아니다

현대의 자바스크립트 엔진은 컴파일과 인터프린터를 전부 사용하여 스크립트를 동작시킨다.

브라우저 개발자툴의 콘솔은 편의를 제공할뿐 브라우저 엔진이 처리하는 것 처럼 똑같이 동작하지 않는다

실제 브라우저 엔진과 미묘하게 틀린 동작이 재현안됨

자바스크립트는 타입을 강제변환한다

“==” 은 비교되는 양쪽 변수의 타입이 틀리다면 한쪽을 변환하여 비교한다. “===” 은 타입까지 비교한다.

하지만 크기비교 연산자나, for문이나 while 문 내에서 자바스크립트는 내부적으로 타입을 강제변환한다.

납득되지 않아도 그냥 받아들이고 사용해야 하는 경우가 있다.

var x = 1;
while (x == true) {
  x = false; // 실행됨
  console.log('실행됨');
}
var x = '안녕하세요';
if (x == true) {
  console.log('실행안됨'); // 실행안됨
}

es 모듈은 파일 자체가 하나의 싱글톤 모듈이다

클래스 모듈

const person = new Person(
  think = '...';
  
  speak() {
    console.log(think);
  }
);

클래식 모듈

const person = (function Person() {
  let think = '...';
  return {
    speak() {
      console.log(think);
    }
  }
})();

es 모듈 (인스턴스가 하나임)

// es모듈은 window 참조가 필요없음

// Person.js
let think = '...'; 

export function speak() {
  console.log(think);
}

자바스크립트의 this는 동적으로 생성됨

내용생략

스코프

function fscope() { // 함수스코프 시작
  let a = 1;
  let b = 1;

  //블록 스코프
  if (true) {
    let a = 3;
  }

  // 블록스코프
  { 
    let a = 3;
  }
}
  • 첫번째인자와 두번째 인자 영역이 모두 스코프임(첫번째 인자가 두번째 인자의 상위 스코프)
function scopeExam(a, b = a) {
  console.log(a, b);
}

클로저

선언시점의 렉시컬스코프 포함 관계를 실행시점에 인스턴스화함

  • 클로저 (b는 메모리에서 제거됨)
const run = wrap();

function wrap(A, B) {
  let a = A;
  let b = B;

  return function() {
    a = a + 1;
    console.log(a);
  }
}

const run = wrap(1, 2);
const run2 = wrap(3, 4);
  • 클로저(a, b를 모드 메모리 해제 안됨)
const run = wrap();

function wrap() {
  let a = 1;
  let b = 2;

  return function() {
    eval('a = a + 1');
    console.log(a);
  }
}
  • 클로저 아님(상위 스코프에서 참조하는 값이 없으므로)

const run = wrap();

function wrap() {
  let a = 1;
  let b = 2;

  return function() {
    console.log('none');
  }
}

프로토타입

클래스를 이용한 객체의 사용도 물론 좋지만. 프로토타입을 이용한 작동 위임 사용방식을 더 권장함. 필자는 시리즈 3권을 읽어보라고 권하고 있음

클래스 방식은 부모 자식 관계가 고착화 되지만 작동위임은 객체 간의 동등한 입장에서 연결하므로서 더 느슨한 연결로 재활용 할수 있다.

더 간단한 디자인으로 구현 가능하고, 부모를 호출하기 위해 super메서드를 이용해야하는 지저분 함이 없어짐.

globalThis

  • 모든 환경에서 globalThis 키워드는 아래 모두를 지칭
    • 브라우저에서는 window
    • webWorker에서는 self
    • node에서는 global

변수 쉐도잉

let 밑의 하위 스코프로 var는 쉐도잉으로 선언하면 안됨

function somthing() {
  var special = "javascript";

  {
    let special = 42;
  }
}
  • 안됨
function somthing() {
  let special = "javascript";

  {
    var special = 42;
  }
}

전역변수는 예상할수 없으므로 함부로 건들면 안된다

동작을 예상하기 힘든 예약어들이 무수히 많다

window.name = 3;

console.log(typeof window.name); // string

호이스팅은 비유일 뿐이다

호이스팅은 코드를 실제로 재정렬 하지 않는다. 우리가 코드를 이해할때 (파싱과 컴파일 단계를 설명할때) 코드과 위로 끌어올려진다고 생각하면 설명하기 쉽기 때문에 비유되어 말하는것 뿐이지 실제로 코드가 재정렬 되지는 않는다.

최소노출의 원칙 (POLE)

시스템 구성요소(예를 들면 변수) 는 관련되어 꼭 필요한 부분에 최소한으로 노출되어야 한다.

  • 이름충돌, 예기치 않은 변이나 작동, 의도치 않게 코드에 커플링이 생기고 인지 부하가 많아짐

  • 작가는 변수 노출을 엄격하게 제한하기 위해 아래와 같은 이중 스코프를 권장함.

function run() {
  let result = 0;
  let a = 1;
  const b = 2;

  if (a < b) {
    a += 1;
  }

  { // c와 d처럼 중간 과정에만 필요한 경우 상위 노출을 제한하기 위해 스코프를 격리시킴
    const c = a + b;
    const d = a + b * 2;
    result = c + d;
  }

  return result;
}
  • IIFE 함수의 괄호는 하나의 스코프임 상위로 노출안됨
(function aa() {
  console.log('a');
})();

console.log(aa); // 참조 에러

블록 내 함수 선언은 예상하기 힘드므로 안하는게 좋다

if (true) {
  function ask() {
    console.log('a');
  }
}
if (true) {
  function ask() {
    console.log('b');
  }
}

function ask() {
  console.log('c');
}

ask();