자바스크립트 4일차

객체(Object)

  • 자바스크립트의 자료구조에는 객체배열이 있다.
  • 객체한꺼번에 여러 값을 담을 수 있는 통(container)과 같은 자료구조(data structure)이다.
  • 객체 안에는 이름-값 쌍(name-value pair)이 저장되는데, 이를 객체의 속성(property)라고 한다.

객체 리터럴(Object Literal)

  • 객체 리터럴에서 속성을 정의할 때는 ''를 써도 되고 안써도 된다.
  • 식별자 규칙을 만족하는 문자열을 속성 이름으로 사용할 때는 따옴표를 생략해도 된다.
  • 식별자 이름 규칙을 만족하지 않는 경우, ''로 감싸줘야 한다.
  • 식별자의 이름에 공백은 허용되지 않으므로 ex) ‘한국 나이’ 따옴표로 둘러싸줘야 한다.
  • ‘한국 나이’: 20 + 3 해도 된다.
    • 표현식의 결과값이 속성값이 된다.

축약 표기법

  • 내가 갖고 있는 변수의 이름과 똑같은 이름을 갖는 속성을 만들고 싶을 때,
1
2
3
4
5
6
7
const name = "윤아준";

const person = {
name, // `name: name`과 똑같이 동작합니다.
age: 19
// ...
};
  • 왼쪽: 속성 이름- name, 오른쪽: 속성 값이 될 표현식- name

객체 리터럴에서 속성을 정의하는 세 가지 방법

  • 아래와 같이 대괄호를 사용해서 다른 변수에 저장된 문자열을 그대로 속성의 이름으로 쓰는 것도 가능합니다.
  • []로 둘러싸여있으면 이 표현식의 결과값이 속성의 이름이 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const propName = 'prop3'

const obj = {
// 아래 두 예제는 왼쪽 부분이 문자열로 간주된다.
// 그리고 그 문자열이 그대로 속성 이름으로 사용된다.
prop1: 1, // prop1이 속성 이름이 된다.
'prop2': 2, // prop2가 속성 이름이 된다.
// 아래 예제는, 대괄호 내부의 표현식의 결과값이
// 속성 이름으로 사용된다.
[propName]: 1 // prop3이 속성 이름이 된다.
[propName + propName]: 1 // prop3prop3이 속성 이름이 된다.
};

// 아래의 표기법들은, 주로 '코드 작성 시점에 속성 이름을 알 수 없는 경우'에 사용된다.

점 표기법, 대괄호 표기법

1
2
3
4
5
6
const person = {}; // 빈 객체

// 점 표기법 (Dot notation)
person.name = "윤아준";
person.age = 19;
person.languages = ["Korean", "English"];
  • 문자열이 그대로 속성 이름으로 사용되는가
  • 표현식의 결과값이 속성 이름으로 사용되는지를 봐야 한다.
  • 객체 리터럴을 통해 이미 만들어진 객체에도 얼마든지 속성을 추가할 수 있다.
  • 속성 접근자를 통해서 접근할 때 식별자 규칙을 만족하는 경우에만 점 표기법을 통해 접근할 수 있다.
  • 식별자 규칙을 만족하지 X경우, 반드시 대괄호 표기법을 사용해야 한다.
1
2
3
4
5
// 대괄호 표기법(Bracket notation)
person.한국 나이 = 20;//이렇게 쓸 수 X. 식별자 이름에 공백이 있어서 쓸 수 X.
person.'한국 나이' = 20;//이렇게 쓸 수 X.
person.['한국 나이'] = 20; // 식별자 규칙을 만족하지 않으므로 []안에 써준다.
person.['한국' +' 나이'] = 20; // 이렇게도 쓸 수 있음. []안에 있는 건 표현식이라는 걸 보여주기 위한 예시 코드
  • 보통 점표기법이 많이 사용되나 대괄호 표기법을 사용해야 하는 경우가 있다.
  • 접근하고자 하는 사용자로부터 입력받은 문자열을 속성 이름으로 사용하고 싶을 경우, 코드 작성 시점에는 어떤 이름이 될지 모르므로 대괄호 표기법을 사용한다.
1
2
3
4
5
6
7
8
// 사용자로부터 입력받은 문자열을 속성 이름으로 사용하는 예제
const propName = prompt("속성 이름을 입력하세요");
const propValue = prompt("속성 값을 입력하세요");

const obj = {};
obj[propName] = propValue;
// propName이라는 변수에 저장되어있는 값을 속성 이름으로 사용하는 경우이므로
// 이때는 사용자가 입력한 값이 속성의 이름이 되는 게 아니라 값이 된다.

객체 다루기

1
2
3
// 속성 삭제하기
delete person.address;
// delete는 연산자이다.

객체의 속성이 삭제되면 true값이 반환된다.
객체의 속성이 사라지는 걸 막는 경우가 있는데 그 경우에는 delete연산자로 속성을 삭제하려고 하면, false값이 반환된다.

1
2
3
4
// 속성이 객체에 존재하는지 확인하기
"name" in person; // true
"phoneNumber" in person; // false
// in도 연산자이다.

메소드 (Method)

1
2
3
4
5
6
7
const person = {
greet: function() {
return "hello";
}
};

person.greet(); // 'hello';
1
2
3
4
5
6
7
8
// 축약 표기법. 위 예제와 완전히 똑같이 동작한다.
const person = {
greet() {
return "hello";
}
};

person.greet(); // 'hello';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const person = {
name: "윤아준",
age: 19,
introduce() {
// `this`를 사용해서 객체의 속성에 접근함
return `안녕하세요, 제 이름은 ${this.name}입니다. 제 나이는 ${
this.age
}살 입니다.`;
},
getOlder() {
// `this`를 사용해서 객체의 속성을 갱신함
this.age += 3;
// 3살 더하기
},
getYounger() {
this.age--;
// 1살 빼기
}
};

// person.introduce(); // '안녕하세요, 제 이름은 윤아준입니다. 제 나이는 19살 입니다.'
person.getOlder(); // undefined
person.introduce(); // '안녕하세요, 제 이름은 윤아준입니다. 제 나이는 20살 입니다.'
  • 객체 리터럴 안에서는 객체 속성값으로 함수를 지정할 때 ,를 찍어줘야 한다.
  • 화살표 함수와 function keyword함수를 사용했을 때는 ‘this’를 사용했을 때, 동작 방식이 다르게 동작한다.

생성자(Constructor)

  • new를 써서 호출하는 함수를 생성자라고 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
// 생성자 정의
function Person(name) {
this.name = name;
this.age = 0;
this.getOlder = function() {
this.age++;
};
}

// 생성자를 통한 객체 생성
const person1 = new Person("윤아준");
person1.getOlder();
console.log(person1); // Person { name: '윤아준', age: 1, getOlder: [Function] }
1
2
3
4
5
6
7
8
9
10
11
12
13
// 생성자 정의
function Person(name, age) {
this.name = name;
this.age = age;
this.getOlder = function() {
this.age++;
};
}

// 생성자를 통한 객체 생성
const person1 = new Person("윤아준", 0);
person1.getOlder();
console.log(person1); //Person { name: '윤아준', age: 1, getOlder: [Function] }

인스턴스 (Instance)

  • 생성자를 통해 생성된 객체를 그 생성자의 인스턴스(instance)라고 한다.
  • instanceof 연산자를 사용하면, 객체가 특정 생성자의 인스턴스가 맞는지를 확인할 수 있다.
1
person1 instanceof Person; // true
1
2
const obj = {};
obj instanceof Object; // true
  • ‘자바스크립트’에서 생성자와 일반적인 함수 간의 차이는 없다.
  • 함수를 생성자로 쓰면 생성자가 되는 것이었다.
  • 이것이 자바스크립트의 부족한 점이었다.
  • ES6에 객체를 만드는 일만 하는 함수인 클래스가 생겼다. 현재는 생성자를 많이 쓰진 않으나 클래스를 이해하려면 생성자를 먼저 이해해야 한다.

프로토 타입

배열

  • 객체에서는 안에 들어있는 값들을 속성, 배열 안에 들어있는 값들을 요소 또는 항목이라고 한다.

배열 생성하기

배열 리터럴

  • 배열 안에 객체 등을 넣을 수 있다.

Array 생성자

  • 자주 쓰이지는 X.
  • 인수를 하나 넘기면 그 개수만큼 빈칸이 있는 비어있는 배열이 만들어진다.
  • 인수가 2개 이상이면 그 인수들을 요소로 갖는 배열을 생성한다.

Array.of

  • Array 생성자의 단점을 보완하기 위해 만들어짐. 자주 쓰이진 X
  • Array.of 메소드를 사용하면 인수가 하나이더라도 그 인수를 요소로 갖는 배열을 반환한다.

Array.from

  • 간간히 사용되는 편임. 외울 것.
1
2
Array.from("hello"); // ["h", "e", "l", "l", "o"]
// 'hello'.split('');으로 만들수도 있음.

요소 읽기

요소 수정하기

fill 메소드

  • 하나의 값으로 배열 전체나 일부분을 채울 수 있다.
  • arr.fill(배열을 채울 값, index시작, index 끝번호-1 )
1
2
3
// 인덱스 2와 4 사이를 1로 채우기
arr.fill(1, 2, 4);
console.log(arr); // [ 0, 0, 1, 1, 0 ];
  • Array 생성자와 fill 메소드를 사용하면, 큰 배열을 만들고 값을 채워넣는 일을 쉽게 할 수 있다.
1
2
// 1000칸의 빈칸이 있는 배열을 만들고 5로 배열을 가득 채운다.
new Array(1000).fill(5); // [5, 5, 5, 5, ...]

배열의 끝 부분에서 요소를 추가/제거하기

배열의 오른쪽 끝 부분에서 요소를 추가/제거하기

push 메소드와 pop 메소드를 사용하면 배열의 오른쪽 끝 부분에서 요소를 추가하거나 제거할 수 있다.
push 메소드 - 배열의 오른쪽에 요소를 추가한다. - push 메소드에 여러 개의 인수를 동시에 넘길 수도 있다.
pop 메소드 - 배열의 오른쪽 맨 끝에 있는 값을 끄집어내서 반환한다. - 배열의 오른쪽 맨 끝에 있는 요소를 삭제한다.

1
2
3
4
5
6
7
8
9
10
11
12
const arr = [];
arr.push("one"); // 1 (요소가 추가된 후의 배열의 길이를 반환)
arr.push("two", "three"); // 결과값: 3
// 배열의 오른쪽에 요소를 추가한다.

console.log(arr); // [ 'one', 'two', 'three' ]

// 배열의 요소 삭제하기
arr.pop(); // 'three'
arr.pop(); // 'two'
arr.pop(); // 'one'
arr.pop(); // undefined (더 이상 배열에 요소가 남아있지 않으면 `undefined`를 반환)

배열의 왼쪽 끝 부분에서 요소를 추가/제거하기

  • 반대로 unshift, shift 메소드를 사용해 배열의 시작 부분(왼쪽 부분)에서 요소를 추가하거나 제거할 수도 있다.
  • 기능은 push 메소드와 pop 메소드와 같으나 방향만 다름.(왼쪽 부분부터)

요소를 배열 중간에 삽입하기

  • splice메소드: 열에 속해있는 연속된 여러 요소, 즉 배열의 일부분을 통째로 바꿔버릴 수 있다.
  • splice메소드
    • 끄집어 낸(바꿔치기 당한) 요소를 끄집어내서 반환한다.
    • 배열의 요소들을 바꿔치치 한다.
    • arr.splice(시작 index 번호, 바꿀 요소의 개수, 바꿔서 채울 요소);
    • splice는 반드시 같은 개수의 요소만 바꿔치기 할 수 있는 게 X.
      끄집어내는 개수와 채우는 개수가 달라도 된다.
1
2
3
let arr = [1, 2, 3, 4, 5];
arr.splice(1, 3, "three"); // [2, 3, 4]
console.log(arr); // [ 1, 'three', 5]
  • 바꿀 요소의 개수 자리에 0을 넣으면 해당 index의 요소를 빼기만 하고 채워지는 건 X.

  • 이렇게 splice 메소드를 배열의 중간 부분에 있는 요소를 제거하는 데도 활용할 수 있다.

  • splice의 두 번째 인수로 0을 사용하면, 특정 위치에 여러 요소를 삽입할 수도 있다.

1
2
3
4
// 인덱스가 `1`인 요소 앞에 여러 요소를 추가합니다.
const arr = [1, 5];
arr.splice(1, 0, 2, 3, 4); // []
console.log(arr); // [ 1, 2, 3, 4, 5]

배열 뒤집기

  • reverse 메소드: 원본 배열을 거꾸로 뒤집어 버린다.
  • 뒤집은 원본 배열을 반환한다.
  • sort 메소드
  • 뭐가 앞에 와야하는지, 뒤에 와야하는지 그 기준이 있어야 한다.
  • sort 메소드를 쓸 때는 비교 함수를 넘겨주어야 한다.
  • 오름차순: 작 -> 큰
  • 내림차순: 큰 -> 작

  • 비교 함수를 인수로 넘겨주지 않으면, sort메소드는 먼저 요소를 전부 문자열올 변환한 후, 유니코드 코드 포인트를 비교하는 방식으로 정렬한다.

1
2
3
4
5
6
7
8
9
10
[20, 3, 100].sort(); // [100, 20, 3]
<!-- 각 숫자를 문자열로 변환 후 첫글자를 비교. -->
<!-- 100은 첫글자가 1, 20의 첫글자: 2, 3의 첫글자: 3이므로 -->
<!-- 유니코드 코드 포인트순으로 정렬 해서 [100, 20, 3]임 -->

['abc', 'DEF', 'aBC'].sort(); // [ 'DEF', 'aBC', 'abc' ]
// 대문자의 유니코드 코드 포인트가 소문자보다 작으므로 'DEF'가 가장 첫 번째 배열의 요소로 정렬된다.

['abc', 'DEF', 'aBC'].sort((x, y) => x.localeCompare(y)); // [ 'abc', 'aBC', 'DEF' ]
// 사전순 비교를 하려면 localeCompare 메소드를 사용한다.

배열의 길이

  • length 속성: 배열의 길이가 변하면서 length 속성의 값도 자동으로 달라진다.
1
2
3
4
5
// 배열의 길이 줄이기 (줄어든 만큼 뒤쪽에 있는 요소들은 버려집니다.)
// 이렇게 사용하는건 권장되지 X. push, pop, shift, unshift 사용해서 할 것.
arr.fill(1);
arr.length = 2;
console.log(arr); // [1, 1]

배열 순회하기

for 구문

forEach 메소드

  • ES5에 추가된 메소드
  • forEach 메소드를 사용하면, 배열의 각 요소에 대해 함수를 호출할 수 있다.
    const arr = [1, 2, 3];
1
2
3
arr.forEach((item) => {
console.log(`현재 요소 ${item}에 대해 함수가 실행되고 있습니다.`);
});
1
2
3
4
const arr = [1, 2, 3];
arr.forEach((item, index, array) => {
console.log(`현재 ${index + 1}번째 요소에 대해 함수가 실행되고 있습니다.`);
});

for..of 구문

  • 현재 가장 많이 사용됨
  • ES6에 추가된 메소드
  • 배열도 반복가능한 객체이다.
  • index가 들어오는 매개변수가 없다.
  • index가 필요없는 경우- for..of 구문을 사용하고,
    index가 필요한 경우 for 구문이나 forEach 구문을 사용하자.

  • 코드의 실행 속도가 가장 빠른 건 for 구문이다. ex) 게임 같이 실행 속도가 중요할 경우에는 for구문을 사용한다.

1
2
3
4
5
const arr = [1, 2, 3, 4, 5];

for (let item of arr) {
console.log(item);
}
1
2
3
4
5
6
const arr = [1, 2, 3];
for (const item of arr) {
console.log(item);
}
// for of 구문에서는 const로 써도 된다. 변수를 매번 새로 생성하기 때문에.
// 변수가 블록 스코프에서만 유효하다.

배열로부터 새로운 값 생성

slice

  • 원본 배열에 변화를 주지 않고, 배열을 복사하고 싶을 때 slice를 사용해서 새로운 배열을 만들고 그 새로운 배열로 작업한다. ex) 원본 배열에 sort하면 원본 배열이 바뀜
  • slice는 얕은 복사를 한다.
  • 배열의 일부분에 해당하는 새로운 배열을 반환한다.
  • 원본 배열에는 아무 변화 X.
  • 첫 번째 인수의 기본값은 0, 두 번째 인수의 기본값은 배열의 length 속성입니다. 즉, 인수 없이 호출하면 배열 전체가 복사된다.

  • arr.slice();와 arr(0, 5);는 같게 작동한다.

  • const는 재대입이 되지 않는 키워드다.

  • 값이 변하지 않는 걸 보장하는 게 X.
1
2
3
const arr = [3, 1, 2, 4, 5];
// arr.sort()하면 원본 배열이 바뀌므로 const로 변수를 만든다고 해서
// 그 값이 변하지 않는 게 X.

map

  • map 메소드는 배열의 각 요소에 함수를 적용해서, 그 반환값을 요소로 갖는 새로운 배열을 만듭니다.
  • forEach와 비슷해 보이지만, 새로운 배열을 만든다는 점이 다르다.

concat

  • concat 메소드는 여러 배열을 연결해서 새 배열을 만들 때 사용된다.
    -

filter

  • 새로운 배열을 생성한다.
  • 원본 배열을 변경하지 않는다.
  • filter 역시 (현재 요소, 인덱스, 배열)의 세 인수를 받는다.

join

  • join 메소드는 배열의 요소들을 문자열로 변환 한 후, 메소드에 주어진 구분자(separator)를 이용해 하나의 문자열로 결합하여 반환한다.
1
2
3
const arr = [1, 2, 3];

arr.join("&"); // '1&2&3'
  • 구분자를 넘기지 않으면, , 문자가 구분자로 사용된다.
1
2
3
const arr = [1, 2, 3];

arr.join(); // '1,2,3'

요소 찾기

  • indexOf 메소드: 배열의 왼쪽부터
  • lastIndexOf 메소드: 오른쪽부터 검색해서 처음 만나는 요소의 인덱스를 반환
1
2
3
4
5
6
7
8
const arr = ["a", "b", "c", "b", "a"];

arr.indexOf("b"); // 1
arr.lastIndexOf("b"); // 3

arr.indexOf("z"); // -1
// 예전에는 이 값이 -1인지 아닌지를 확인해서 이 요소가 배열에 있는지 없는지를 판별했었음.
arr.lastIndexOf("z"); // -1
  • find
  • findIndex

배열이 특정 조건을 만족하는지 판별하기

  • includes 메소드

    • 배열이 특정 요소를 포함하고 있는지를 판별
    • 진리값을 반환
  • every 메소드

    • 모든 요소가 조건을 만족하면 true, 하나라도 조건을 만족하지 않으면 false를 반환
    • &&를 이어붙인 느낌
  • some 메소드

    • 하나라도 조건을 만족하면 true, 모두 조건을 만족하지 않으면 false 반환
    • ||를 이어붙인 느낌

배열인지 아닌지 판별하기

  • Array.isArray 사용(중요하진 X)

문자열과 배열

  • 문자열의 메소드 중에는 배열의 메소드 중에 몇몇과 이름이 같고 완전히 같은 방식으로 동작하는 것들이 있다.
1
2
3
4
5
"hello"[0]; // 'h'
"hello".slice(2, 4); // 'll'
for (let c of "hello") {
console.log(c);
}

다차원 배열 (Multidimensional Array)

  • 표, 좌표, 게임판 등을 저장하기 위해서 많이 사용된다.
1
2
3
4
const table = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

table[0][1]; // 2
table[2][0]; // 7