충남대학교 컴퓨터공학과 이규철 교수님의 "웹 프로그래밍" 강의를 필기한 내용입니다.

다소 잘못된 내용과 구어적 표현 이 포함되어 있을 수 있습니다.

본 문서는 작성자의 귀찮음 때문에 참고 문서 링크들로 범벅되어 있습니다.

Array 몰랐던점

배열 순회

const arr = [1, 2, 3];
 
for(const el of arr) {
	console.log(el);
}
  • 뒤에 가서 또 나오겠지만 배열의 순회에는 for-of를 써야 하고 객체의 순회에는 for-in을 써야 한다 - 순서가 중요한 경우에는 for-in을, 순서가 중요하지 않은 경우에는 for-of를 사용해라

배열의 출력

10%20-%20JS%20Basic%202%201d9b1ed519da4750aeff8aee672ff4f1/image1.png

  • innerHTML에 배열을 넣으면 위처럼 나온다

배열 인덱스로 값 넣기

const fruits = ["Banana", "Orange", "Apple"];
fruits[6] = "Lemon";
  • 위 코드를 실행시키면

10%20-%20JS%20Basic%202%201d9b1ed519da4750aeff8aee672ff4f1/image2.png

  • OutOfBounds 에러가 나는게 아니고 위처럼 저장된다

Array() 생성자의 인자

  • new Array(10, 20); 은 배열에 10과 20을 넣어주지만
  • new Array(40); 은 크기가 40짜리인 배열을 만든다

삽입과 삭제

  • Array.shift().pop_front() 와 같은거고
  • Array.unshift(el).push_front(el) 와 같은거임
  • delete 는 원소를 지우긴 하지만 그자리를 undefined 로 만들어버린댄다
  • Array.splice() 는 주어진 인덱스에서 주어진 갯수만큼 원소를 지우고 주어진 원소들로 다시 채운 후 반환하는 메소드임

정렬 예시

순회 예시

Object

Object Literal

  • 자바스크립트는 보통의 다른언어와 다르게 객체 리터럴(Object Literal) 이 존재한다.
{
	id: 1234,
	name: "holymoly",
	age: 24,
}
  • 위와 같은 구조를 Object Literal 이라고 하는데
  • 뭐 많이 써봤으니까 익숙하긴 할거임
  • 근데 여기서 중요한 것은 Object Literal 과 ES6에서부터 지원하는 class 키워드, 그리고 function + prototype 을 이용한 객체의 생성은 별개의 것이 아니라는 것을 아는 것이다
  • 즉, 문자열을 const str = new String() 를 이용해 만들 수도 있지만 const str = "" 처럼 Literal을 이용해 만들 수 있듯이
  • 객체도 new 를 이용해 만들 수도 있고 {} 를 이용해 만들 수도 있는 것이다

Prototype의 이해

  • 자바스크립트는 Prototype Design Pattern 을 이용하는 대표적인 언어다
  • ES6부터는 class 키워드를 지원해 객체를 만들 수 있는 또다른 방법이 생겼지만
  • 결국에는 class 키워드는 이전의 prototype 을 이용한 객체의 생성방식을 문법과 제약조건만 좀 바꾼 Syntactic Sugar 의 일종이지 작동방식은 prototype 을 여전히 사용하게 된다
  • 일단 다른 언어와 자바스크립트의 객체 생성 방식을 좀 더 살펴보면
  • 자바같은 언어는 객체를 new 키워드를 이용해 생성하면 생성자가 클래스를 바탕으로 객체를 생성해서 준다
  • 하지만 이러한 방식은 객체를 생성하는데 꽤나 많은 자원이 필요하기 때문에 자바스크립트는 Prototype 이라는 것을 이용한다
  • 그래서 이게 뭐냐면
  • 생성자를 정의하면 생성자 뿐만 아니라 객체의 원형 - 이게 Prototype 이다 - 도 생성하고 new 를 이용해 객체를 생성하면 밑바닥부터 만드는게 아니고 Prototype 객체를 복사해서 주는 방식이다
  • 뭐 요즘은 컴퓨터가 다 빨라서 체감도 잘 안되고 진짜 그런진 모르겠는데 이게 더 빠르다네
  • 그럼 이 생성자는 으케만드는가
  • function 키워드를 이용해 함수를 정의하면 이놈이 생성자의 권한을 갖게 된다
    • 뭐 ES6에 와서는 arrow function을 지원하면서 진짜 함수같은 함수가 생겼지만 그냥 함수랑 생성자 권한을 가진 함수랑 좀 분리를 시켜놓던지 왜 이렇게 했는지는 알 방법이 없음
    • function 안에서 this 키워드를 쓸 수 있는 이유가 바로 이거때문
  • 그럼 정리해보면
    • function 을 이용해 함수를 정의하면 이놈이 생성자의 권한을 부여받고 동시에 prototype 객체가 생성되어 어딘가에 저장되게 된다
    • 그리고 new 키워드를 이용해 객체를 생성하면 저장해놓은 prototype 을 복사한 다음 property들을 세팅해서 반환하는 구조인 셈이다
  • 그럼 이 prototype 에는 어떻게 접근하는가
  • 모든 function 에는 .prototype 이라는 property가 존재해 이것을 이용해 prototype 을 수정할 수 있다
  • 따라서 아래의 코드는
function Person() {}
console.log(Person.prototype);
  • 결과가 다음과 같이 나온다 (크롬 기준)
Object { constructor: f Person(), [[Prototype]] }
  • 그리고 .prototype 에 보면 constructor() 라는 함수가 있다는 것을 알 수 있는데
  • 이놈이 아까 선언한 생성자를 가리키게 된다

10%20-%20JS%20Basic%202%201d9b1ed519da4750aeff8aee672ff4f1/image3.png

  • 따라서 위와 같은 구조가 된다
  • 함수에는 prototype property 가 있어서 property 를 참조할 수 있고 property 에는 constructor 가 있어서 다시 원래 함수를 가리키게 되는 원형적이라고 할 수 있는 방식이다
  • 그리고 저기 보면 __proto__ 라는 놈이 있는데 이놈은 생성자를 이용해 생성된 객체에 포함되어 원본 prototype을 참조할 수 있게 해주는 것이다

10%20-%20JS%20Basic%202%201d9b1ed519da4750aeff8aee672ff4f1/image4.png

  • 즉, 이렇게 된다 이거임
  • 복사되는 원본객체를 Prototype Object라 하고 생성된 객체에 있는 __proto__Prototype Link 라 하며 Prototype ObjectPrototype Link 를 합쳐서 Prototype 라고 용어를 사용하더라

생성자 선언 종합

  • 객체가 생성될때 복사되길 원하는 것들을 prototype 에 넣어주고 객체마다 다른 값을 가질 수 있는 property같은것들은 그냥 this 키워드를 이용해 정의한다
function Person(name, age) {
	this.name = name;
	this.age = age;
}
 
Person.prototype.getName = function() {
	return this.name;
}
 
Person.prototype.getAge = function() {
	return this.age;
}
  • 근데 주의할건 Method를 생성자 밖에서 정의할때는 arrow function을 사용하면 this 키워드가 안먹기 때문에 function 키워드를 사용해야 된다
function Person(name, age) {
	this.name = name;
	this.age = age;
 
	// 가능
	Person.prototype.getAge = () => {
		return this.age;
	}
}
 
// 불가능
Person.prototype.getName = () => {
	return this.name;
}
  • 그리고 Property를 prototype에 넣는 경우 해당 프로퍼티는 객체들마다 같은 값을 가지기 때문에 이 값을 변경할 경우 다른 객체에서도 바뀐다는 것을 꼭 기억하고있으라

멤버를 찾는 방법

  • 프로토타입 방식에서 객체의 멤버에 접근할때 우선 해당 객체에 해당 멤버가 있는지 확인하고, 없으면 그놈의 프로토타입 객체에서 확인하고, 없으면 또 그놈의 프로토타입으로 거슬러 올라가는 방식으로 해당 멤버에 접근할 수 있는지 확인하게 된다

몰랐던거 정리

순회

const obj = {
	aa: 1,
	bb: 2,
	cc: 3,
};
 
for(let key in obj) {
	console.log(`${key}: ${obj[key]}`);
}
 
Object.entries(obj).forEach(([key, val]) => {
	console.log(`${key}: ${val}`);
});
  • 주의할점은
    1. for-in구문은 순회 순서가 보장되지 않는다 - 배열에서 인덱스 0번부터 차례대로 순회한다고 보장할 수 없음 - 따라서 객체에서만 해당 구문을 써야된다
    2. foreach 가 아니고 forEach 라는 것
    3. Object.entries().forEach 에 사용하는 함수는 배열 인자를 받도록 되어 있다 - 따라서 파라미터를 배열형식으로 구성하면 배열의 원소를 바로 받아올 수 있음
  • 이외에도 Key만 순회하는 Object.prototype.keys() 하고 값만 순회하는 Object.prototype.values() 도 있으니 필요하면 그때 찾아보자

제거

  • delete 키워드를 사용하면 객체에서 프로퍼티를 삭제할 수 있다
  • delete 키워드를 사용해서 프로토타입에서도 지울 수 있으나 객체 전체에 영향을 미치기 때문에 신중해야 한다는 것

Getter, Setter

const obj = {
	this.name = "";
 
	get uname() {
		return this.name;
	},
 
	set uname(arg) {
		this.name = arg.toUpperCase();
	}
};
 
obj.uname = "abcdef";
console.log(obj.uname);
  • 뭐 이렇게 getter setter 문법으로 간단하게 프로퍼티값 조회 및 변경시 추가적인 행동을 지정해 줄 수 있는 것알고있제?

Date

10%20-%20JS%20Basic%202%201d9b1ed519da4750aeff8aee672ff4f1/image5.png

Boolean

  • 이건 좀 알고있어라 - truthy와 falsy를 boolean으로 바꿔주는 것!!(falsy expression)

Set

  • 중복 없는 자료구조
  • new Set()
  • Set.prototype.add()
  • 뭐 순회를 위한 forEach(), values(), keys() 를 지원함
  • entries() 도 있는데 Set의 경우에는 Key가 없기 때문에 [value, value] 형태로 반환한댄다

Map