JavaScript Koans

JiHun·2023년 5월 1일
0

JavaScript

목록 보기
1/5

Review

여태 배운걸 돌아보는 시간. 알고 있지만 중요한 것, 새로 배운 것 위주로 정리하자.

💼 알고 있지만 중요한 것

🗂️ let, const

const로 선언된 변수에는 재할당이 금지 되어있다. 객체 전체를 재할당하는 건 안되지만 객체의 속성을 추가하거나 삭제할 수 있다.

const arr = [];
const num1 = 1;
arr.push(num1)       // arr => [1]
// arr = [1, 2, 3]   // 배열 전체 재할당 금지
const obj = { x: 1 }
obj.y = 2;            //  arr => { x:1, y:2 }
// obj = { x:1111 }      // 객체 전체 재할당은 금지

consletvar보다 쓰는 걸 권장한다. 이거는 납득이 된다. var로 선언된 변수는 모두 전역 변수로 취급하기 때문에... 그리고 let은 재할당도 가능한데 왜 const가 따로 존재할까? 변경되길 원치 않는 변수를 위해 사용한다. 재할당이 장점이 될 수도 있지만 단점이 될 수도 있다. 단점을 보완하기 위해 const를 쓰는 거 같다.

🗂️ Scope

📑 함수 선언(declaration)식과 함수 표현(expression)식

let Expressed = "Expressed"
function Declared() {
	return "this is a function declaration";
}

Expressed = function() {
	return "this is a function expression";
}

typeof Declared   // => "function"
typeof Expressed  // => "function"

함수 표현식은 let으로 선언되는 경우, 변수명에 재할당할 수 있다.

📑 default parameter

function defaultPrice(price = 4) {
	return price
}
defaultParameter()  // 4;
defaultParameter(8) // 8;
function pushNum(num, arr = []) {
	arr.push(num);
  	return arr;
}
pushNum(10);            // arr => [10]
pushNum(4, [1, 2, 3])   // arr => [1, 2, 3, 4]

📑 lexical scope

scope는 함수를 선언할 때 생긴다.
선언하는 순간, 함수 내부의 변수는 자기 스코프부터 가장 가까운 곳(상위 범위)에 있는 변수를 계속 참조하게 된다.

let message = "Outer"
    
function getMessage() {
  return message;
}

function shadowGlobal() {
  let message = "Inner";
  return message;
}
function shadowGlobal2(message) {
  return message;
}
function shadowParameter(message) {
  message = "HI";
  return message
}

함수 순서대로 보자.

  • 첫번째 함수 => 함수 내부에 message를 선언한게 없다. 따라서 상위 함수에 있는 환경을 가져와 message는 "Outer"를 리턴한다.
  • 두번째 함수 => 함수 내부에 let으로 같은 변수명을 가진 값을 선언했다. 여기 함수 내에서는 message가 "Inner"로 쓰인다. 따라서 "Inner"를 리턴한다.
  • 세번째 함수 => 파라미터로 들어온 message는 함수 내부에서만 작동하기 때문에 let message = "xxx"과 같은 방식으로 돌아간다. 따라서 "xxx"가 리턴된다.
  • 네번째 함수 => 파리미터로 들어온 message가 있어서 let message = "xxx"가 있지만 다시 재할당해서 "HI"가 리턴된다. 재할당은 지역 함수에서만 먹히고 전역변수는 건드리지 않는다.

📑 closure

클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다.

function multipleBy(multipleByAmount) {
	return function (numberToMultiple) {
    	return numberToMultiple * multipleByAmount;
    }
}

const multipleBy3 = multipleBy(3);
const multipleBy5 = multipleBy(5);

multipleBy3(10);                     // => 30;
multipleBy5(10);                     // => 50;
multipleBy(2)(7) + multipleBy(5)(3)  // => 29;

multipeBy3multipleBy5 함수는 클로저 함수다. 함수의 정의 본문은 공유하지만 서로 다른 어휘(맥락)적 환경을 저장한다. multipleBy3은 multipleByAmount 파라미터를 3으로 환경에 세팅해 놓은 상태다. 마찬가지로 MultipleBy5은 multipleByAmount 파라미너를 5로 환경에 세팅한 상태다.

🗂️ Types

📑 참조 자료형을 변수에 할당할 경우, 데이터의 주소가 저장된다.

const nums1 = [1, 2, 3];
const nums2 = [1 ,2, 3];
nums1 === nums2  // false;  nums1과 nums2 서로 주소값이 다르다.

[1, 2, 3]  // 데이터가 heap에 저장되지만 변수 할당이 되지 않아 주소는 어디에도 저장되지 않는다.
nums1 === [1, 2, 3];   // false; 서로 다른 주소에 저장되었기 때문에 false가 된다.

🗂️ Array

📑 Array를 함수의 전달인자로 전달할 경우, reference가 전달된다.

const arr = ["0", "1", "2", "3", "4", "5"];
function passedByReference(refArr) {
	refArr[1] = "changed in function";
}
passedByReference(arr);    // => ["0", "changed in function", "2", "3", "4", "5"];

const assignedArr = arr;   // 그냥 복사. 주소값이 같다.
assignedArr[5] = "changed in assignedArr";
arr[5]  // => "changed in assignedArr"

const copiedArr = arr.slice();   // => 얕은 복사. 주소값이 다르다.
copiedArr[3] = "changed in copiedArr";
arr[3] // => "three"

🗂️ Object

📑 'this'는 method를 호출하는 시점에 결정됩니다.

const cal = {
	prop:14,
  	func: function() {
    	return this.prop
	}
}

console.log(cal.func());  // 14;

함수가 호출 될때마다 그 함수는 "어떤 객체"의 method일 것이다. 호출될 때마다 그 "어떤 객체"를 물어보는 것이 this

🗂️ Spread syntax

const spread = [1, 2, 3];
const arr = [0, ...spread, 4];   // [0, 1, 2, 3, 4];
  • 빈 배열을 전개 문법을 사용할 경우, 아무것도 전달되지 않는다.
  • Rest Parameter는 함수의 전달인자를 배열로 다룰 수 있게 한다.
  • Rest Parameter는 전달 인자의 수가 정해져 있지 않은 경우에도 유용하게 사용할 수 있다.
  • Rest Parameter는 전달인자의 일부에만 적용할 수도 있다.

🗂️ Destructuring

📑 rest/apread 문법을 사용

const array = ["one", "two", "three", "four"];
const [start, ...rest] = array;
console.log(start);     // "one"
console.log(rest);      // ["two", "three", "four"]

순서대로 start 부분에 "one"을 넣고 ...rest에 나머지를 넣고 배열을 반환한다.

📑 객체의 단축 문법

const name = "홍길동";
const age = 18;

const person = {
	name,
	age,
  	isFather: false,
}

person 객체 안에 name, age는 단축된 문법이다. 사실은 name: name, age: age를 단축한 것이다.

💼 새로 알게된 사실

🗂️ 함수 호이스팅(hoisting)

함수의 코드를 실행하기 전에 함수 선언에 대한 메모리부터 할당한다. 덕분에 함수를 호출하는 코드를 함수 선언보다 앞서 배치 가능하다.
변수의 선언과 초기화를 분리 한후, 선언만 코드의 최상단으로 옮기는 것.
함수 호출이 함수 자체보다 앞서 존재하지만, 함수는 이미 선언돼서 존재한다.
웃긴건 함수 표현식은 호이스팅이 안되고 함수 선언시만 호이스팅이 된다.

console.log(Declared());   // => "this is a function expression"

function Declared() {
	return "this is a function expression";
}
profile
안녕하세요. 프론트엔드 개발자 송지훈입니다.

0개의 댓글